@@ -142,18 +142,19 @@ type wgtun struct {
142142 refreshBa * core.Barrier [bool , string ] // 2mins refresh barrier
143143
144144 // TODO: move status to a state-machine for all proxies
145- status * core.Volatile [int ] // status of this interface
146- latestRefresh atomic.Int64 // last refresh time in unix millis
147- latestPing atomic.Int64 // last ping time in unix millis
148- latestErr core.Volatile [error ] // last open/dial err
149- latestRxErr core.Volatile [error ] // last rx error
150- latestTxErr core.Volatile [error ] // last tx error
151- latestGoodRx atomic.Int64 // last successful rx time in unix millis
152- latestGoodTx atomic.Int64 // last successful tx time in unix millis
153- latestRx atomic.Int64 // last (successful or not) rx time in unix millis
154- latestTx atomic.Int64 // last (successful or not) tx time in unix millis
155- errRx atomic.Int64 // rx error count
156- errTx atomic.Int64 // tx error count
145+ status * core.Volatile [int ] // status of this interface
146+ statusReason core.Volatile [string ] // last state transition reason
147+ latestRefresh atomic.Int64 // last refresh time in unix millis
148+ latestPing atomic.Int64 // last ping time in unix millis
149+ latestErr core.Volatile [error ] // last open/dial err
150+ latestRxErr core.Volatile [error ] // last rx error
151+ latestTxErr core.Volatile [error ] // last tx error
152+ latestGoodRx atomic.Int64 // last successful rx time in unix millis
153+ latestGoodTx atomic.Int64 // last successful tx time in unix millis
154+ latestRx atomic.Int64 // last (successful or not) rx time in unix millis
155+ latestTx atomic.Int64 // last (successful or not) tx time in unix millis
156+ errRx atomic.Int64 // rx error count
157+ errTx atomic.Int64 // tx error count
157158}
158159
159160type wgconn interface {
@@ -1190,6 +1191,7 @@ func (w *wgproxy) Stat() (out *x.RouterStats) {
11901191 out .LastRefresh = w .latestRefresh .Load ()
11911192 out .Since = w .since
11921193 out .Status = pxstatus (w .status .Load ()).String ()
1194+ out .StatusReason = w .statusReason .Load ()
11931195
11941196 if w .status .Load () == END {
11951197 log .W ("proxy: wg: %s stats: stopped" , w .tag ())
@@ -1585,14 +1587,12 @@ func (h *wgtun) serve(network, local string) (pc net.PacketConn, err error) {
15851587
15861588func (h * wgtun ) listener (op wg.PktDir , err error ) {
15871589 s := h .status .Load ()
1588- if err != nil {
1589- if op .Read () {
1590- h .latestRxErr .Store (err )
1591- } else if op .Write () {
1592- h .latestTxErr .Store (err )
1593- } else {
1594- h .latestErr .Store (err )
1595- }
1590+ if op .Read () {
1591+ h .latestRxErr .Store (err )
1592+ } else if op .Write () {
1593+ h .latestTxErr .Store (err )
1594+ } else {
1595+ h .latestErr .Store (err )
15961596 }
15971597
15981598 if s == END || s == TPU { // stopped or paused
@@ -1607,6 +1607,7 @@ func (h *wgtun) listener(op wg.PktDir, err error) {
16071607 why := ""
16081608
16091609 defer func () {
1610+ h .statusReason .Store (why )
16101611 cur := h .status .Load ()
16111612 stoppedOrPaused := cur == END || cur == TPU
16121613 updated := false
@@ -1659,6 +1660,7 @@ func (h *wgtun) listener(op wg.PktDir, err error) {
16591660 } // else: not a transport message
16601661 }
16611662
1663+ softrefresh := false
16621664 const tenSecMillis = 10 * 1000
16631665 // s may also be TOK (for successful handshakes but not for transport data)
16641666 if age > tenSecMillis && (s == TOK || s == TKO ) {
@@ -1689,13 +1691,14 @@ func (h *wgtun) listener(op wg.PktDir, err error) {
16891691 why = "TZZ: idling after start/refresh"
16901692 s = TZZ // possibly idling
16911693 } else if readThres || writeThres || readWriteDeviation {
1692- why = fmt .Sprintf ("TNT : r !ok? %t, w !ok? %t, rw apart? %t; overriding: %s" ,
1694+ why = fmt .Sprintf ("TZZ : r !ok? %t, w !ok? %t, rw apart? %t; overriding: %s" ,
16931695 readThres , writeThres , readWriteDeviation , why )
1694- s = TNT
1696+ s = TZZ
1697+ softrefresh = true
16951698 }
16961699 }
16971700
1698- if s == TNT {
1701+ if s == TNT || softrefresh {
16991702 m := h .dns .Load ().SoftRefresh ()
17001703 if n := h .remote .Load ().MaybeRefresh (); n > 0 {
17011704 log .I ("wg: %s listener: %s, state: %s; refreshed %d dns / %d peers; why: %s" ,
0 commit comments