Cycle every payload pattern per packet and always run both directions
This commit is contained in:
@@ -10,10 +10,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// A stream number no data stream can take, so a probe is never mistaken for
|
||||
// payload if one lands on the wrong socket.
|
||||
probeStream = 0xffff
|
||||
probeSize = 64
|
||||
// Above any real stream number, so a probe is never taken for payload.
|
||||
probeStream = 0xffff
|
||||
probeSize = 64
|
||||
probePattern = 0
|
||||
|
||||
// The mac has only a handful of transmit stamp slots. Asking faster than it
|
||||
// can drain them gets slots recycled while a stamp is still outstanding, and
|
||||
@@ -27,10 +27,9 @@ const (
|
||||
)
|
||||
|
||||
// Both ports hang off one PTP clock, so a transmit stamp from one and a receive
|
||||
// stamp from the other subtract directly. Both are taken at the mac, so the
|
||||
// difference is the two phys plus the cable and nothing else: all host time and
|
||||
// all queueing falls outside the stamped interval, which is why load does not
|
||||
// move it.
|
||||
// stamp from the other subtract directly. Both are taken at the mac, so all host
|
||||
// time and all queueing falls outside the stamped interval, which is why load
|
||||
// does not move it.
|
||||
type cableStats struct {
|
||||
mu sync.Mutex
|
||||
min int64
|
||||
@@ -52,10 +51,10 @@ func (v cableView) minText() string {
|
||||
return commasInt(v.min)
|
||||
}
|
||||
|
||||
// Summing both directions cancels the phy asymmetry between them, which is
|
||||
// Averaging the two directions cancels the phy asymmetry between them, which is
|
||||
// about 790ns and swamps any cable, so one direction alone cannot give a length.
|
||||
func (c config) cableMetres(views []view) (float64, bool) {
|
||||
if len(views) != 2 {
|
||||
if len(views) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
var sum float64
|
||||
@@ -65,7 +64,8 @@ func (c config) cableMetres(views []view) (float64, bool) {
|
||||
}
|
||||
sum += float64(v.cable.min)
|
||||
}
|
||||
return (sum - c.zeroNS) / c.nsPerM, true
|
||||
mean := sum / float64(len(views))
|
||||
return (mean - c.zeroNS) / c.nsPerM, true
|
||||
}
|
||||
|
||||
func (c config) cableText(views []view) string {
|
||||
@@ -83,8 +83,6 @@ func newCableStats() *cableStats {
|
||||
}
|
||||
}
|
||||
|
||||
// The two halves are produced by different goroutines in either order, so each
|
||||
// deposits its stamp and whichever lands second completes the pair.
|
||||
func (c *cableStats) put(seq uint64, ts int64, tx bool) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
@@ -133,8 +131,6 @@ func (c *cableStats) reset() {
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// Sends one small frame at a time and collects its transmit stamp from the
|
||||
// socket's error queue before sending the next.
|
||||
type probeSender struct {
|
||||
fd int
|
||||
spec *frameSpec
|
||||
@@ -143,7 +139,7 @@ type probeSender struct {
|
||||
|
||||
func (p *probeSender) run(done *atomic.Bool, startTx <-chan struct{}) {
|
||||
buf := make([]byte, probeSize)
|
||||
p.spec.prefill(buf)
|
||||
p.spec.prefill(buf, probePattern)
|
||||
oob := make([]byte, 512)
|
||||
scratch := make([]byte, 1)
|
||||
|
||||
@@ -156,9 +152,8 @@ func (p *probeSender) run(done *atomic.Bool, startTx <-chan struct{}) {
|
||||
for !done.Load() {
|
||||
<-tick.C
|
||||
|
||||
// Stamps are matched to sends by position in the queue, so a stamp that
|
||||
// arrived after its probe gave up would be handed to this one. Discard
|
||||
// anything left over before sending.
|
||||
// Stamps are matched to sends by position in the queue, so one that
|
||||
// arrived after its probe gave up would be handed to this probe.
|
||||
for {
|
||||
if _, _, _, _, err := unix.Recvmsg(p.fd, scratch, oob,
|
||||
unix.MSG_ERRQUEUE|unix.MSG_DONTWAIT); err != nil {
|
||||
@@ -166,8 +161,8 @@ func (p *probeSender) run(done *atomic.Bool, startTx <-chan struct{}) {
|
||||
}
|
||||
}
|
||||
|
||||
putHeader(buf, p.spec.patIdx, probeStream, seq, probeSize-minFrame,
|
||||
p.spec.crcFor[probeSize])
|
||||
putHeader(buf, probePattern, probeStream, seq, probeSize-minFrame,
|
||||
p.spec.crcFor[probePattern][probeSize])
|
||||
err := unix.Send(p.fd, buf, 0)
|
||||
// The sequence advances even when a probe fails, so a stale receive half
|
||||
// can never be paired with a later probe that reused its number.
|
||||
@@ -211,8 +206,6 @@ func (p *probeSender) awaitTx(scratch, oob []byte) (int64, bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// Reads probes on the far interface, where every frame carries a receive stamp
|
||||
// from the MAC.
|
||||
type probeReceiver struct {
|
||||
fd int
|
||||
stats *cableStats
|
||||
|
||||
Reference in New Issue
Block a user