14
14
* limitations under the License.
15
15
*/
16
16
17
- mod error;
17
+ pub ( crate ) mod error;
18
18
pub mod packet_router;
19
19
mod sessions;
20
20
21
- cfg_if:: cfg_if! {
22
- if #[ cfg( target_os = "linux" ) ] {
23
- pub ( crate ) mod io_uring_shared;
24
- pub ( crate ) type PacketSendReceiver = io_uring_shared:: EventFd ;
25
- pub ( crate ) type PacketSendSender = io_uring_shared:: EventFdWriter ;
26
- } else {
27
- pub ( crate ) type PacketSendReceiver = tokio:: sync:: watch:: Receiver <bool >;
28
- pub ( crate ) type PacketSendSender = tokio:: sync:: watch:: Sender <bool >;
29
- }
30
- }
31
-
32
- /// A simple packet queue that signals when a packet is pushed
33
- ///
34
- /// For io_uring this notifies an eventfd that will be processed on the next
35
- /// completion loop
36
- #[ derive( Clone ) ]
37
- pub struct PendingSends {
38
- packets : Arc < parking_lot:: Mutex < Vec < SendPacket > > > ,
39
- notify : PacketSendSender ,
40
- }
41
-
42
- impl PendingSends {
43
- pub fn new ( capacity : usize ) -> std:: io:: Result < ( Self , PacketSendReceiver ) > {
44
- #[ cfg( target_os = "linux" ) ]
45
- let ( notify, rx) = {
46
- let rx = io_uring_shared:: EventFd :: new ( ) ?;
47
- ( rx. writer ( ) , rx)
48
- } ;
49
- #[ cfg( not( target_os = "linux" ) ) ]
50
- let ( notify, rx) = tokio:: sync:: watch:: channel ( true ) ;
51
-
52
- Ok ( (
53
- Self {
54
- packets : Arc :: new ( parking_lot:: Mutex :: new ( Vec :: with_capacity ( capacity) ) ) ,
55
- notify,
56
- } ,
57
- rx,
58
- ) )
59
- }
60
-
61
- #[ inline]
62
- pub ( crate ) fn capacity ( & self ) -> usize {
63
- self . packets . lock ( ) . capacity ( )
64
- }
65
-
66
- /// Pushes a packet onto the queue to be sent, signalling a sender that
67
- /// it's available
68
- #[ inline]
69
- pub ( crate ) fn push ( & self , packet : SendPacket ) {
70
- self . packets . lock ( ) . push ( packet) ;
71
- #[ cfg( target_os = "linux" ) ]
72
- self . notify . write ( 1 ) ;
73
- #[ cfg( not( target_os = "linux" ) ) ]
74
- let _ = self . notify . send ( true ) ;
75
- }
76
-
77
- /// Called to shutdown the consumer side of the sends (ie the io loop that is
78
- /// actually dequing and sending packets)
79
- #[ inline]
80
- pub ( crate ) fn shutdown_receiver ( & self ) {
81
- #[ cfg( target_os = "linux" ) ]
82
- self . notify . write ( 0xdeadbeef ) ;
83
- #[ cfg( not( target_os = "linux" ) ) ]
84
- let _ = self . notify . send ( false ) ;
85
- }
86
-
87
- /// Swaps the current queue with an empty one so we only lock for a pointer swap
88
- #[ inline]
89
- pub fn swap ( & self , mut swap : Vec < SendPacket > ) -> Vec < SendPacket > {
90
- swap. clear ( ) ;
91
- std:: mem:: replace ( & mut self . packets . lock ( ) , swap)
92
- }
93
- }
94
-
95
21
use super :: RunArgs ;
96
22
pub use error:: { ErrorMap , PipelineError } ;
97
23
pub use sessions:: SessionPool ;
@@ -103,20 +29,6 @@ use std::{
103
29
} ,
104
30
} ;
105
31
106
- pub struct SendPacket {
107
- /// The destination address of the packet
108
- pub destination : socket2:: SockAddr ,
109
- /// The packet data being sent
110
- pub data : crate :: collections:: FrozenPoolBuffer ,
111
- /// The asn info for the sender, used for metrics
112
- pub asn_info : Option < crate :: net:: maxmind_db:: MetricsIpNetEntry > ,
113
- }
114
-
115
- pub struct RecvPacket {
116
- pub source : SocketAddr ,
117
- pub data : crate :: collections:: PoolBuffer ,
118
- }
119
-
120
32
#[ derive( Clone , Debug ) ]
121
33
pub struct Ready {
122
34
pub idle_request_interval : std:: time:: Duration ,
@@ -156,7 +68,7 @@ pub struct Proxy {
156
68
pub management_servers : Vec < tonic:: transport:: Endpoint > ,
157
69
pub to : Vec < SocketAddr > ,
158
70
pub to_tokens : Option < ToTokens > ,
159
- pub socket : socket2:: Socket ,
71
+ pub socket : Option < socket2:: Socket > ,
160
72
pub qcmp : socket2:: Socket ,
161
73
pub phoenix : crate :: net:: TcpListener ,
162
74
pub notifier : Option < tokio:: sync:: mpsc:: UnboundedSender < String > > ,
@@ -173,7 +85,7 @@ impl Default for Proxy {
173
85
management_servers : Vec :: new ( ) ,
174
86
to : Vec :: new ( ) ,
175
87
to_tokens : None ,
176
- socket : crate :: net:: raw_socket_with_reuse ( 0 ) . unwrap ( ) ,
88
+ socket : Some ( crate :: net:: raw_socket_with_reuse ( 0 ) . unwrap ( ) ) ,
177
89
qcmp,
178
90
phoenix,
179
91
notifier : None ,
@@ -183,15 +95,16 @@ impl Default for Proxy {
183
95
184
96
impl Proxy {
185
97
pub async fn run (
186
- self ,
98
+ mut self ,
187
99
RunArgs {
188
100
config,
189
101
ready,
190
102
mut shutdown_rx,
191
103
} : RunArgs < Ready > ,
192
104
initialized : Option < tokio:: sync:: oneshot:: Sender < ( ) > > ,
193
105
) -> crate :: Result < ( ) > {
194
- let _mmdb_task = self . mmdb . map ( |source| {
106
+ let _mmdb_task = self . mmdb . as_ref ( ) . map ( |source| {
107
+ let source = source. clone ( ) ;
195
108
tokio:: spawn ( async move {
196
109
while let Err ( error) =
197
110
tryhard:: retry_fn ( || crate :: MaxmindDb :: update ( source. clone ( ) ) )
@@ -205,7 +118,7 @@ impl Proxy {
205
118
} ) ;
206
119
207
120
if !self . to . is_empty ( ) {
208
- let endpoints = if let Some ( tt) = self . to_tokens {
121
+ let endpoints = if let Some ( tt) = & self . to_tokens {
209
122
let ( unique, overflow) = 256u64 . overflowing_pow ( tt. length as _ ) ;
210
123
if overflow {
211
124
panic ! (
@@ -355,28 +268,7 @@ impl Proxy {
355
268
. expect ( "failed to spawn proxy-subscription thread" ) ;
356
269
}
357
270
358
- let num_workers = self . num_workers . get ( ) ;
359
- let buffer_pool = Arc :: new ( crate :: collections:: BufferPool :: new ( num_workers, 2 * 1024 ) ) ;
360
-
361
- let mut worker_sends = Vec :: with_capacity ( num_workers) ;
362
- let mut session_sends = Vec :: with_capacity ( num_workers) ;
363
- for _ in 0 ..num_workers {
364
- let psends = PendingSends :: new ( 15 ) ?;
365
- session_sends. push ( psends. 0 . clone ( ) ) ;
366
- worker_sends. push ( psends) ;
367
- }
368
-
369
- let sessions = SessionPool :: new ( config. clone ( ) , session_sends, buffer_pool. clone ( ) ) ;
370
-
371
- packet_router:: spawn_receivers (
372
- config. clone ( ) ,
373
- self . socket ,
374
- worker_sends,
375
- & sessions,
376
- buffer_pool,
377
- )
378
- . await ?;
379
-
271
+ let router_shutdown = self . spawn_packet_router ( config. clone ( ) ) . await ?;
380
272
crate :: codec:: qcmp:: spawn ( self . qcmp , shutdown_rx. clone ( ) ) ?;
381
273
crate :: net:: phoenix:: spawn (
382
274
self . phoenix ,
@@ -395,8 +287,50 @@ impl Proxy {
395
287
. await
396
288
. map_err ( |error| eyre:: eyre!( error) ) ?;
397
289
398
- sessions . shutdown ( * shutdown_rx . borrow ( ) == crate :: ShutdownKind :: Normal ) ;
290
+ ( router_shutdown ) ( shutdown_rx ) ;
399
291
400
292
Ok ( ( ) )
401
293
}
294
+
295
+ pub async fn spawn_packet_router (
296
+ & mut self ,
297
+ config : Arc < crate :: config:: Config > ,
298
+ ) -> eyre:: Result < impl FnOnce ( crate :: ShutdownRx ) > {
299
+ self . spawn_user_space_router ( config) . await
300
+ }
301
+
302
+ /// Launches the user space implementation of the packet router using
303
+ /// sockets. This implementation uses a pool of buffers and sockets to
304
+ /// manage UDP sessions and sockets. On Linux this will use io-uring, where
305
+ /// as it will use epoll interfaces on non-Linux platforms.
306
+ pub async fn spawn_user_space_router (
307
+ & mut self ,
308
+ config : Arc < crate :: config:: Config > ,
309
+ ) -> eyre:: Result < impl FnOnce ( crate :: ShutdownRx ) > {
310
+ let workers = self . num_workers . get ( ) ;
311
+ let buffer_pool = Arc :: new ( crate :: collections:: BufferPool :: new ( workers, 2 * 1024 ) ) ;
312
+
313
+ let mut worker_sends = Vec :: with_capacity ( workers) ;
314
+ let mut session_sends = Vec :: with_capacity ( workers) ;
315
+ for _ in 0 ..workers {
316
+ let queue = crate :: net:: queue ( 15 ) ?;
317
+ session_sends. push ( queue. 0 . clone ( ) ) ;
318
+ worker_sends. push ( queue) ;
319
+ }
320
+
321
+ let sessions = SessionPool :: new ( config. clone ( ) , session_sends, buffer_pool. clone ( ) ) ;
322
+
323
+ packet_router:: spawn_receivers (
324
+ config,
325
+ self . socket . take ( ) . unwrap ( ) ,
326
+ worker_sends,
327
+ & sessions,
328
+ buffer_pool,
329
+ )
330
+ . await ?;
331
+
332
+ Ok ( move |shutdown_rx : crate :: ShutdownRx | {
333
+ sessions. shutdown ( * shutdown_rx. borrow ( ) == crate :: ShutdownKind :: Normal ) ;
334
+ } )
335
+ }
402
336
}
0 commit comments