|
|
@ -34,6 +34,7 @@ import (
|
|
|
|
"tailscale.com/tailcfg"
|
|
|
|
"tailscale.com/tailcfg"
|
|
|
|
"tailscale.com/types/logger"
|
|
|
|
"tailscale.com/types/logger"
|
|
|
|
"tailscale.com/types/opt"
|
|
|
|
"tailscale.com/types/opt"
|
|
|
|
|
|
|
|
"tailscale.com/util/clientmetric"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// Debugging and experimentation tweakables.
|
|
|
|
// Debugging and experimentation tweakables.
|
|
|
@ -232,6 +233,12 @@ func (c *Client) MakeNextReportFull() {
|
|
|
|
func (c *Client) ReceiveSTUNPacket(pkt []byte, src netaddr.IPPort) {
|
|
|
|
func (c *Client) ReceiveSTUNPacket(pkt []byte, src netaddr.IPPort) {
|
|
|
|
c.vlogf("received STUN packet from %s", src)
|
|
|
|
c.vlogf("received STUN packet from %s", src)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if src.IP().Is4() {
|
|
|
|
|
|
|
|
metricSTUNRecv4.Add(1)
|
|
|
|
|
|
|
|
} else if src.IP().Is6() {
|
|
|
|
|
|
|
|
metricSTUNRecv6.Add(1)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.mu.Lock()
|
|
|
|
c.mu.Lock()
|
|
|
|
if c.handleHairSTUNLocked(pkt, src) {
|
|
|
|
if c.handleHairSTUNLocked(pkt, src) {
|
|
|
|
c.mu.Unlock()
|
|
|
|
c.mu.Unlock()
|
|
|
@ -737,7 +744,13 @@ func (c *Client) udpBindAddr() string {
|
|
|
|
// GetReport gets a report.
|
|
|
|
// GetReport gets a report.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// It may not be called concurrently with itself.
|
|
|
|
// It may not be called concurrently with itself.
|
|
|
|
func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (*Report, error) {
|
|
|
|
func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report, reterr error) {
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
|
|
|
|
if reterr != nil {
|
|
|
|
|
|
|
|
metricNumGetReportError.Add(1)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
metricNumGetReport.Add(1)
|
|
|
|
// Mask user context with ours that we guarantee to cancel so
|
|
|
|
// Mask user context with ours that we guarantee to cancel so
|
|
|
|
// we can depend on it being closed in goroutines later.
|
|
|
|
// we can depend on it being closed in goroutines later.
|
|
|
|
// (User ctx might be context.Background, etc)
|
|
|
|
// (User ctx might be context.Background, etc)
|
|
|
@ -769,6 +782,7 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (*Report, e
|
|
|
|
last = nil // causes makeProbePlan below to do a full (initial) plan
|
|
|
|
last = nil // causes makeProbePlan below to do a full (initial) plan
|
|
|
|
c.nextFull = false
|
|
|
|
c.nextFull = false
|
|
|
|
c.lastFull = now
|
|
|
|
c.lastFull = now
|
|
|
|
|
|
|
|
metricNumGetReportFull.Add(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rs.incremental = last != nil
|
|
|
|
rs.incremental = last != nil
|
|
|
|
c.mu.Unlock()
|
|
|
|
c.mu.Unlock()
|
|
|
@ -983,6 +997,7 @@ func (c *Client) runHTTPOnlyChecks(ctx context.Context, last *Report, rs *report
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (c *Client) measureHTTPSLatency(ctx context.Context, reg *tailcfg.DERPRegion) (time.Duration, netaddr.IP, error) {
|
|
|
|
func (c *Client) measureHTTPSLatency(ctx context.Context, reg *tailcfg.DERPRegion) (time.Duration, netaddr.IP, error) {
|
|
|
|
|
|
|
|
metricHTTPSend.Add(1)
|
|
|
|
var result httpstat.Result
|
|
|
|
var result httpstat.Result
|
|
|
|
ctx, cancel := context.WithTimeout(httpstat.WithHTTPStat(ctx, &result), overallProbeTimeout)
|
|
|
|
ctx, cancel := context.WithTimeout(httpstat.WithHTTPStat(ctx, &result), overallProbeTimeout)
|
|
|
|
defer cancel()
|
|
|
|
defer cancel()
|
|
|
@ -1217,6 +1232,7 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe
|
|
|
|
|
|
|
|
|
|
|
|
switch probe.proto {
|
|
|
|
switch probe.proto {
|
|
|
|
case probeIPv4:
|
|
|
|
case probeIPv4:
|
|
|
|
|
|
|
|
metricSTUNSend4.Add(1)
|
|
|
|
n, err := rs.pc4.WriteTo(req, addr)
|
|
|
|
n, err := rs.pc4.WriteTo(req, addr)
|
|
|
|
if n == len(req) && err == nil {
|
|
|
|
if n == len(req) && err == nil {
|
|
|
|
rs.mu.Lock()
|
|
|
|
rs.mu.Lock()
|
|
|
@ -1224,6 +1240,7 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe
|
|
|
|
rs.mu.Unlock()
|
|
|
|
rs.mu.Unlock()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case probeIPv6:
|
|
|
|
case probeIPv6:
|
|
|
|
|
|
|
|
metricSTUNSend6.Add(1)
|
|
|
|
n, err := rs.pc6.WriteTo(req, addr)
|
|
|
|
n, err := rs.pc6.WriteTo(req, addr)
|
|
|
|
if n == len(req) && err == nil {
|
|
|
|
if n == len(req) && err == nil {
|
|
|
|
rs.mu.Lock()
|
|
|
|
rs.mu.Lock()
|
|
|
@ -1322,3 +1339,15 @@ func conciseOptBool(b opt.Bool, trueVal string) string {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
|
|
|
metricNumGetReport = clientmetric.NewCounter("netcheck_report")
|
|
|
|
|
|
|
|
metricNumGetReportFull = clientmetric.NewCounter("netcheck_report_full")
|
|
|
|
|
|
|
|
metricNumGetReportError = clientmetric.NewCounter("netcheck_report_error")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
metricSTUNSend4 = clientmetric.NewCounter("netcheck_stun_send_ipv4")
|
|
|
|
|
|
|
|
metricSTUNSend6 = clientmetric.NewCounter("netcheck_stun_send_ipv6")
|
|
|
|
|
|
|
|
metricSTUNRecv4 = clientmetric.NewCounter("netcheck_stun_recv_ipv4")
|
|
|
|
|
|
|
|
metricSTUNRecv6 = clientmetric.NewCounter("netcheck_stun_recv_ipv6")
|
|
|
|
|
|
|
|
metricHTTPSend = clientmetric.NewCounter("netcheck_https_measure")
|
|
|
|
|
|
|
|
)
|
|
|
|