@@ -47,6 +47,7 @@ import (
47
47
"tailscale.com/tstime/rate"
48
48
"tailscale.com/types/key"
49
49
"tailscale.com/types/logger"
50
+ "tailscale.com/util/ctxkey"
50
51
"tailscale.com/util/mak"
51
52
"tailscale.com/util/set"
52
53
"tailscale.com/util/slicesx"
@@ -57,6 +58,16 @@ import (
57
58
// verbosely log whenever DERP drops a packet.
58
59
var verboseDropKeys = map [key.NodePublic ]bool {}
59
60
61
+ // IdealNodeHeader is the HTTP request header sent on DERP HTTP client requests
62
+ // to indicate that they're connecting to their ideal (Region.Nodes[0]) node.
63
+ // The HTTP header value is the name of the node they wish they were connected
64
+ // to. This is an optional header.
65
+ const IdealNodeHeader = "Ideal-Node"
66
+
67
+ // IdealNodeContextKey is the context key used to pass the IdealNodeHeader value
68
+ // from the HTTP handler to the DERP server's Accept method.
69
+ var IdealNodeContextKey = ctxkey .New [string ]("ideal-node" , "" )
70
+
60
71
func init () {
61
72
keys := envknob .String ("TS_DEBUG_VERBOSE_DROPS" )
62
73
if keys == "" {
@@ -133,6 +144,7 @@ type Server struct {
133
144
sentPong expvar.Int // number of pong frames enqueued to client
134
145
accepts expvar.Int
135
146
curClients expvar.Int
147
+ curClientsNotIdeal expvar.Int
136
148
curHomeClients expvar.Int // ones with preferred
137
149
dupClientKeys expvar.Int // current number of public keys we have 2+ connections for
138
150
dupClientConns expvar.Int // current number of connections sharing a public key
@@ -603,6 +615,9 @@ func (s *Server) registerClient(c *sclient) {
603
615
}
604
616
s .keyOfAddr [c .remoteIPPort ] = c .key
605
617
s .curClients .Add (1 )
618
+ if c .isNotIdealConn {
619
+ s .curClientsNotIdeal .Add (1 )
620
+ }
606
621
s .broadcastPeerStateChangeLocked (c .key , c .remoteIPPort , c .presentFlags (), true )
607
622
}
608
623
@@ -693,6 +708,9 @@ func (s *Server) unregisterClient(c *sclient) {
693
708
if c .preferred {
694
709
s .curHomeClients .Add (- 1 )
695
710
}
711
+ if c .isNotIdealConn {
712
+ s .curClientsNotIdeal .Add (- 1 )
713
+ }
696
714
}
697
715
698
716
// addPeerGoneFromRegionWatcher adds a function to be called when peer is gone
@@ -809,8 +827,8 @@ func (s *Server) accept(ctx context.Context, nc Conn, brw *bufio.ReadWriter, rem
809
827
return fmt .Errorf ("receive client key: %v" , err )
810
828
}
811
829
812
- clientAP , _ := netip .ParseAddrPort (remoteAddr )
813
- if err := s .verifyClient (ctx , clientKey , clientInfo , clientAP .Addr ()); err != nil {
830
+ remoteIPPort , _ := netip .ParseAddrPort (remoteAddr )
831
+ if err := s .verifyClient (ctx , clientKey , clientInfo , remoteIPPort .Addr ()); err != nil {
814
832
return fmt .Errorf ("client %v rejected: %v" , clientKey , err )
815
833
}
816
834
@@ -820,8 +838,6 @@ func (s *Server) accept(ctx context.Context, nc Conn, brw *bufio.ReadWriter, rem
820
838
ctx , cancel := context .WithCancel (ctx )
821
839
defer cancel ()
822
840
823
- remoteIPPort , _ := netip .ParseAddrPort (remoteAddr )
824
-
825
841
c := & sclient {
826
842
connNum : connNum ,
827
843
s : s ,
@@ -838,6 +854,7 @@ func (s *Server) accept(ctx context.Context, nc Conn, brw *bufio.ReadWriter, rem
838
854
sendPongCh : make (chan [8 ]byte , 1 ),
839
855
peerGone : make (chan peerGoneMsg ),
840
856
canMesh : s .isMeshPeer (clientInfo ),
857
+ isNotIdealConn : IdealNodeContextKey .Value (ctx ) != "" ,
841
858
peerGoneLim : rate .NewLimiter (rate .Every (time .Second ), 3 ),
842
859
}
843
860
@@ -1511,6 +1528,7 @@ type sclient struct {
1511
1528
peerGone chan peerGoneMsg // write request that a peer is not at this server (not used by mesh peers)
1512
1529
meshUpdate chan struct {} // write request to write peerStateChange
1513
1530
canMesh bool // clientInfo had correct mesh token for inter-region routing
1531
+ isNotIdealConn bool // client indicated it is not its ideal node in the region
1514
1532
isDup atomic.Bool // whether more than 1 sclient for key is connected
1515
1533
isDisabled atomic.Bool // whether sends to this peer are disabled due to active/active dups
1516
1534
debug bool // turn on for verbose logging
@@ -1546,6 +1564,9 @@ func (c *sclient) presentFlags() PeerPresentFlags {
1546
1564
if c .canMesh {
1547
1565
f |= PeerPresentIsMeshPeer
1548
1566
}
1567
+ if c .isNotIdealConn {
1568
+ f |= PeerPresentNotIdeal
1569
+ }
1549
1570
if f == 0 {
1550
1571
return PeerPresentIsRegular
1551
1572
}
@@ -2051,6 +2072,7 @@ func (s *Server) ExpVar() expvar.Var {
2051
2072
m .Set ("gauge_current_file_descriptors" , expvar .Func (func () any { return metrics .CurrentFDs () }))
2052
2073
m .Set ("gauge_current_connections" , & s .curClients )
2053
2074
m .Set ("gauge_current_home_connections" , & s .curHomeClients )
2075
+ m .Set ("gauge_current_notideal_connections" , & s .curClientsNotIdeal )
2054
2076
m .Set ("gauge_clients_total" , expvar .Func (func () any { return len (s .clientsMesh ) }))
2055
2077
m .Set ("gauge_clients_local" , expvar .Func (func () any { return len (s .clients ) }))
2056
2078
m .Set ("gauge_clients_remote" , expvar .Func (func () any { return len (s .clientsMesh ) - len (s .clients ) }))
0 commit comments