2
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
5
- use crate :: err;
6
- use crate :: packet:: Control ;
5
+ use crate :: packet:: { Control , State as PacketState } ;
7
6
use crate :: {
8
7
bidi, inf, packet, trc, util:: update_peer_info, wrn, BfdPeerState , PeerInfo ,
9
8
} ;
9
+ use crate :: { err, SessionCounters } ;
10
10
use anyhow:: { anyhow, Result } ;
11
11
use slog:: { warn, Logger } ;
12
12
use std:: net:: IpAddr ;
@@ -48,6 +48,7 @@ pub struct StateMachine {
48
48
required_rx : Duration ,
49
49
detection_multiplier : u8 ,
50
50
kill_switch : Arc < AtomicBool > ,
51
+ counters : Arc < SessionCounters > ,
51
52
log : Logger ,
52
53
}
53
54
@@ -64,6 +65,7 @@ impl StateMachine {
64
65
peer : IpAddr ,
65
66
required_rx : Duration ,
66
67
detection_multiplier : u8 ,
68
+ counters : Arc < SessionCounters > ,
67
69
log : Logger ,
68
70
) -> Self {
69
71
let state = Down :: new ( peer, log. clone ( ) ) ;
@@ -73,6 +75,7 @@ impl StateMachine {
73
75
required_rx,
74
76
detection_multiplier,
75
77
kill_switch : Arc :: new ( AtomicBool :: new ( false ) ) ,
78
+ counters,
76
79
log,
77
80
}
78
81
}
@@ -122,6 +125,7 @@ impl StateMachine {
122
125
let peer = self . peer ;
123
126
let kill_switch = self . kill_switch . clone ( ) ;
124
127
let log = self . log . clone ( ) ;
128
+ let counters = self . counters . clone ( ) ;
125
129
spawn ( move || loop {
126
130
let prev = state. read ( ) . unwrap ( ) . state ( ) ;
127
131
let ( st, ep) = match state. read ( ) . unwrap ( ) . run (
@@ -130,6 +134,7 @@ impl StateMachine {
130
134
remote. clone ( ) ,
131
135
kill_switch. clone ( ) ,
132
136
db. clone ( ) ,
137
+ counters. clone ( ) ,
133
138
) {
134
139
Ok ( result) => result,
135
140
Err ( _) => break ,
@@ -143,6 +148,23 @@ impl StateMachine {
143
148
}
144
149
145
150
if prev != new {
151
+ match new {
152
+ BfdPeerState :: AdminDown | BfdPeerState :: Down => {
153
+ counters
154
+ . transition_to_down
155
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
156
+ }
157
+ BfdPeerState :: Init => {
158
+ counters
159
+ . transition_to_init
160
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
161
+ }
162
+ BfdPeerState :: Up => {
163
+ counters
164
+ . transition_to_up
165
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
166
+ }
167
+ }
146
168
inf ! ( log, prev, peer; "transition -> {:?}" , new) ;
147
169
}
148
170
} ) ;
@@ -162,6 +184,7 @@ impl StateMachine {
162
184
let peer = self . peer ;
163
185
let stop = self . kill_switch . clone ( ) ;
164
186
let log = self . log . clone ( ) ;
187
+ let counters = self . counters . clone ( ) ;
165
188
// State does not change for the lifetime of the trait so it's safe to
166
189
// just copy it out of self for sending into the spawned thread. The
167
190
// reason this is a dynamic method at all is to get runtime polymorphic
@@ -203,6 +226,13 @@ impl StateMachine {
203
226
204
227
if let Err ( e) = sender. send ( ( peer, pkt) ) {
205
228
wrn ! ( log, st, peer; "send: {}" , e) ;
229
+ counters
230
+ . control_packet_send_failures
231
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
232
+ } else {
233
+ counters
234
+ . control_packets_sent
235
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
206
236
}
207
237
} ) ;
208
238
}
@@ -255,6 +285,7 @@ pub(crate) trait State: Sync + Send {
255
285
remote : Arc < Mutex < PeerInfo > > ,
256
286
kill_switch : Arc < AtomicBool > ,
257
287
db : rdb:: Db ,
288
+ counters : Arc < SessionCounters > ,
258
289
) -> Result < ( Box < dyn State > , BfdEndpoint ) > ;
259
290
260
291
/// Return the `BfdPeerState` associated with the implementor of this trait.
@@ -297,13 +328,42 @@ pub(crate) trait State: Sync + Send {
297
328
local : PeerInfo ,
298
329
remote : & Arc < Mutex < PeerInfo > > ,
299
330
log : Logger ,
331
+ counters : Arc < SessionCounters > ,
300
332
) -> Result < RecvResult > {
301
333
match endpoint. rx . recv_timeout (
302
334
local. required_min_rx * local. detection_multiplier . into ( ) ,
303
335
) {
304
336
Ok ( ( addr, msg) ) => {
305
337
trc ! ( log, self . state( ) , self . peer( ) ; "recv: {:?}" , msg) ;
306
338
339
+ match msg. state ( ) {
340
+ PacketState :: Peer ( BfdPeerState :: AdminDown ) => {
341
+ counters
342
+ . admin_down_status_received
343
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
344
+ }
345
+ PacketState :: Peer ( BfdPeerState :: Down ) => {
346
+ counters
347
+ . down_status_received
348
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
349
+ }
350
+ PacketState :: Peer ( BfdPeerState :: Init ) => {
351
+ counters
352
+ . init_status_received
353
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
354
+ }
355
+ PacketState :: Peer ( BfdPeerState :: Up ) => {
356
+ counters
357
+ . up_status_received
358
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
359
+ }
360
+ PacketState :: Unknown ( _) => {
361
+ counters
362
+ . unknown_status_received
363
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
364
+ }
365
+ }
366
+
307
367
update_peer_info ( remote, & msg) ;
308
368
309
369
if msg. poll ( ) {
@@ -320,6 +380,7 @@ pub(crate) trait State: Sync + Send {
320
380
}
321
381
Err ( std:: sync:: mpsc:: RecvTimeoutError :: Timeout ) => {
322
382
wrn ! ( log, self . state( ) , self . peer( ) ; "timeout expired" ) ;
383
+ counters. timeout_expired . fetch_add ( 1 , Ordering :: Relaxed ) ;
323
384
let next = Down :: new ( self . peer ( ) , log. clone ( ) ) ;
324
385
Ok ( RecvResult :: TransitionTo ( Box :: new ( next) ) )
325
386
}
@@ -331,6 +392,9 @@ pub(crate) trait State: Sync + Send {
331
392
"recv: {}, exiting recieve loop" ,
332
393
e
333
394
) ;
395
+ counters
396
+ . message_receive_error
397
+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
334
398
Err ( anyhow:: anyhow!( "recv channel closed" ) )
335
399
}
336
400
}
@@ -372,6 +436,7 @@ impl State for Down {
372
436
remote : Arc < Mutex < PeerInfo > > ,
373
437
kill_switch : Arc < AtomicBool > ,
374
438
db : rdb:: Db ,
439
+ counters : Arc < SessionCounters > ,
375
440
) -> Result < ( Box < dyn State > , BfdEndpoint ) > {
376
441
match self . peer {
377
442
IpAddr :: V4 ( addr) => db. disable_nexthop4 ( addr) ,
@@ -384,13 +449,18 @@ impl State for Down {
384
449
}
385
450
loop {
386
451
// Get an incoming message
387
- let ( _addr, msg) =
388
- match self . recv ( & endpoint, local, & remote, self . log . clone ( ) ) ? {
389
- RecvResult :: MessageFrom ( ( addr, control) ) => ( addr, control) ,
390
- RecvResult :: TransitionTo ( state) => {
391
- return Ok ( ( state, endpoint) )
392
- }
393
- } ;
452
+ let ( _addr, msg) = match self . recv (
453
+ & endpoint,
454
+ local,
455
+ & remote,
456
+ self . log . clone ( ) ,
457
+ counters. clone ( ) ,
458
+ ) ? {
459
+ RecvResult :: MessageFrom ( ( addr, control) ) => ( addr, control) ,
460
+ RecvResult :: TransitionTo ( state) => {
461
+ return Ok ( ( state, endpoint) )
462
+ }
463
+ } ;
394
464
395
465
if kill_switch. load ( Ordering :: Relaxed ) {
396
466
return Err ( anyhow ! ( "killed" ) ) ;
@@ -455,16 +525,22 @@ impl State for Init {
455
525
remote : Arc < Mutex < PeerInfo > > ,
456
526
kill_switch : Arc < AtomicBool > ,
457
527
_db : rdb:: Db ,
528
+ counters : Arc < SessionCounters > ,
458
529
) -> Result < ( Box < dyn State > , BfdEndpoint ) > {
459
530
loop {
460
531
// Get an incoming message
461
- let ( _addr, msg) =
462
- match self . recv ( & endpoint, local, & remote, self . log . clone ( ) ) ? {
463
- RecvResult :: MessageFrom ( ( addr, control) ) => ( addr, control) ,
464
- RecvResult :: TransitionTo ( state) => {
465
- return Ok ( ( state, endpoint) )
466
- }
467
- } ;
532
+ let ( _addr, msg) = match self . recv (
533
+ & endpoint,
534
+ local,
535
+ & remote,
536
+ self . log . clone ( ) ,
537
+ counters. clone ( ) ,
538
+ ) ? {
539
+ RecvResult :: MessageFrom ( ( addr, control) ) => ( addr, control) ,
540
+ RecvResult :: TransitionTo ( state) => {
541
+ return Ok ( ( state, endpoint) )
542
+ }
543
+ } ;
468
544
469
545
if kill_switch. load ( Ordering :: Relaxed ) {
470
546
return Err ( anyhow ! ( "killed" ) ) ;
@@ -527,6 +603,7 @@ impl State for Up {
527
603
remote : Arc < Mutex < PeerInfo > > ,
528
604
kill_switch : Arc < AtomicBool > ,
529
605
db : rdb:: Db ,
606
+ counters : Arc < SessionCounters > ,
530
607
) -> Result < ( Box < dyn State > , BfdEndpoint ) > {
531
608
match self . peer {
532
609
IpAddr :: V4 ( addr) => db. enable_nexthop4 ( addr) ,
@@ -539,13 +616,18 @@ impl State for Up {
539
616
}
540
617
loop {
541
618
// Get an incoming message
542
- let ( _addr, msg) =
543
- match self . recv ( & endpoint, local, & remote, self . log . clone ( ) ) ? {
544
- RecvResult :: MessageFrom ( ( addr, control) ) => ( addr, control) ,
545
- RecvResult :: TransitionTo ( state) => {
546
- return Ok ( ( state, endpoint) )
547
- }
548
- } ;
619
+ let ( _addr, msg) = match self . recv (
620
+ & endpoint,
621
+ local,
622
+ & remote,
623
+ self . log . clone ( ) ,
624
+ counters. clone ( ) ,
625
+ ) ? {
626
+ RecvResult :: MessageFrom ( ( addr, control) ) => ( addr, control) ,
627
+ RecvResult :: TransitionTo ( state) => {
628
+ return Ok ( ( state, endpoint) )
629
+ }
630
+ } ;
549
631
550
632
if kill_switch. load ( Ordering :: Relaxed ) {
551
633
return Err ( anyhow ! ( "killed" ) ) ;
0 commit comments