diff --git a/prober/derp.go b/prober/derp.go index 3bb479327..310e25a9d 100644 --- a/prober/derp.go +++ b/prober/derp.go @@ -152,9 +152,7 @@ func (d *derpProber) probeMesh(from, to string) ProbeFunc { } d.Unlock() - // TODO: instead of ignoring latency, export it as a separate metric. - _, err := derpProbeNodePair(ctx, dm, fromN, toN) - return err + return derpProbeNodePair(ctx, dm, fromN, toN) } } @@ -205,15 +203,14 @@ func (d *derpProber) updateMap(ctx context.Context) error { func (d *derpProber) ProbeUDP(ipaddr string, port int) ProbeFunc { return func(ctx context.Context) error { - _, err := derpProbeUDP(ctx, ipaddr, port) - return err + return derpProbeUDP(ctx, ipaddr, port) } } -func derpProbeUDP(ctx context.Context, ipStr string, port int) (latency time.Duration, err error) { +func derpProbeUDP(ctx context.Context, ipStr string, port int) error { pc, err := net.ListenPacket("udp", ":0") if err != nil { - return 0, err + return err } defer pc.Close() uc := pc.(*net.UDPConn) @@ -228,7 +225,7 @@ func derpProbeUDP(ctx context.Context, ipStr string, port int) (latency time.Dur ip := net.ParseIP(ipStr) _, err := uc.WriteToUDP(req, &net.UDPAddr{IP: ip, Port: port}) if err != nil { - return 0, err + return err } // Binding requests and responses are fairly small (~40 bytes), // but in practice a STUN response can be up to the size of the @@ -240,38 +237,35 @@ func derpProbeUDP(ctx context.Context, ipStr string, port int) (latency time.Dur d := time.Since(t0) if err != nil { if ctx.Err() != nil { - return 0, fmt.Errorf("timeout reading from %v: %v", ip, err) + return fmt.Errorf("timeout reading from %v: %v", ip, err) } if d < time.Second { - return 0, fmt.Errorf("error reading from %v: %v", ip, err) + return fmt.Errorf("error reading from %v: %v", ip, err) } time.Sleep(100 * time.Millisecond) continue } txBack, _, err := stun.ParseResponse(buf[:n]) if err != nil { - return 0, fmt.Errorf("parsing STUN response from %v: %v", ip, err) + return fmt.Errorf("parsing STUN response from %v: %v", ip, err) } if txBack != tx { - return 0, fmt.Errorf("read wrong tx back from %v", ip) - } - if latency == 0 || d < latency { - latency = d + return fmt.Errorf("read wrong tx back from %v", ip) } break } - return latency, nil + return nil } -func derpProbeNodePair(ctx context.Context, dm *tailcfg.DERPMap, from, to *tailcfg.DERPNode) (latency time.Duration, err error) { +func derpProbeNodePair(ctx context.Context, dm *tailcfg.DERPMap, from, to *tailcfg.DERPNode) (err error) { fromc, err := newConn(ctx, dm, from) if err != nil { - return 0, err + return err } defer fromc.Close() toc, err := newConn(ctx, dm, to) if err != nil { - return 0, err + return err } defer toc.Close() @@ -282,23 +276,20 @@ func derpProbeNodePair(ctx context.Context, dm *tailcfg.DERPMap, from, to *tailc time.Sleep(100 * time.Millisecond) // pretty arbitrary } - latency, err = runDerpProbeNodePair(ctx, from, to, fromc, toc) - if err != nil { + if err := runDerpProbeNodePair(ctx, from, to, fromc, toc); err != nil { // Record pubkeys on failed probes to aid investigation. - err = fmt.Errorf("%s -> %s: %w", + return fmt.Errorf("%s -> %s: %w", fromc.SelfPublicKey().ShortString(), toc.SelfPublicKey().ShortString(), err) } - return latency, err + return err } -func runDerpProbeNodePair(ctx context.Context, from, to *tailcfg.DERPNode, fromc, toc *derphttp.Client) (latency time.Duration, err error) { +func runDerpProbeNodePair(ctx context.Context, from, to *tailcfg.DERPNode, fromc, toc *derphttp.Client) error { // Make a random packet pkt := make([]byte, 8) crand.Read(pkt) - t0 := time.Now() - // Send the random packet. sendc := make(chan error, 1) go func() { @@ -306,10 +297,10 @@ func runDerpProbeNodePair(ctx context.Context, from, to *tailcfg.DERPNode, fromc }() select { case <-ctx.Done(): - return 0, fmt.Errorf("timeout sending via %q: %w", from.Name, ctx.Err()) + return fmt.Errorf("timeout sending via %q: %w", from.Name, ctx.Err()) case err := <-sendc: if err != nil { - return 0, fmt.Errorf("error sending via %q: %w", from.Name, err) + return fmt.Errorf("error sending via %q: %w", from.Name, err) } } @@ -333,20 +324,20 @@ func runDerpProbeNodePair(ctx context.Context, from, to *tailcfg.DERPNode, fromc }() select { case <-ctx.Done(): - return 0, fmt.Errorf("timeout receiving from %q: %w", to.Name, ctx.Err()) + return fmt.Errorf("timeout receiving from %q: %w", to.Name, ctx.Err()) case v := <-recvc: if err, ok := v.(error); ok { - return 0, fmt.Errorf("error receiving from %q: %w", to.Name, err) + return fmt.Errorf("error receiving from %q: %w", to.Name, err) } p := v.(derp.ReceivedPacket) if p.Source != fromc.SelfPublicKey() { - return 0, fmt.Errorf("got data packet from unexpected source, %v", p.Source) + return fmt.Errorf("got data packet from unexpected source, %v", p.Source) } if !bytes.Equal(p.Data, pkt) { - return 0, fmt.Errorf("unexpected data packet %q", p.Data) + return fmt.Errorf("unexpected data packet %q", p.Data) } } - return time.Since(t0), nil + return nil } func newConn(ctx context.Context, dm *tailcfg.DERPMap, n *tailcfg.DERPNode) (*derphttp.Client, error) {