Count link and syscall failures instead of printing them
This commit is contained in:
@@ -44,7 +44,6 @@ type direction struct {
|
||||
streams []lossWindow
|
||||
txFDs []int
|
||||
rxFDs []int
|
||||
reports chan string
|
||||
|
||||
probeSpec *frameSpec
|
||||
probeTxFD int
|
||||
@@ -59,8 +58,8 @@ type direction struct {
|
||||
drops uint64
|
||||
errBase sample
|
||||
dropBase uint64
|
||||
nicTX nicCounters
|
||||
nicRX nicCounters
|
||||
nicNow uint64
|
||||
nicBase uint64
|
||||
}
|
||||
|
||||
// Smoothing has to be steady against high-frequency noise yet still chase a
|
||||
@@ -192,6 +191,7 @@ type sample struct {
|
||||
crcErr, badMagic uint64
|
||||
badLen uint64
|
||||
txErrs, txShort uint64
|
||||
rxErrs uint64
|
||||
}
|
||||
|
||||
func lookupEndpoint(name string) (endpoint, error) {
|
||||
@@ -247,6 +247,7 @@ func (d *direction) snapshot() sample {
|
||||
s.crcErr += r.crcErr.Load()
|
||||
s.badMagic += r.badMagic.Load()
|
||||
s.badLen += r.badLen.Load()
|
||||
s.rxErrs += r.rxErrs.Load()
|
||||
}
|
||||
for i := range d.streams {
|
||||
s.lost += d.streams[i].lost.Load()
|
||||
@@ -264,6 +265,7 @@ func (d *direction) reset() {
|
||||
d.dropBase = d.drops
|
||||
d.heldFrames = heldValue{}
|
||||
d.heldSent = heldValue{}
|
||||
d.nicBase = d.nicNow
|
||||
d.cable.reset()
|
||||
}
|
||||
|
||||
@@ -300,7 +302,8 @@ var intervalCols = []colSpec{
|
||||
{title: "CRC", width: 7, right: true},
|
||||
{title: "BADMAG", width: 7, right: true},
|
||||
{title: "KDROP", width: 11, right: true},
|
||||
{title: "ERRORS", width: 11, right: true},
|
||||
{title: "LINK", width: 13, right: true},
|
||||
{title: "ERRORS", width: 13, right: true},
|
||||
{title: "MIN ns", width: 9, right: true},
|
||||
{title: "LEN m", width: 6, right: true},
|
||||
}
|
||||
@@ -314,7 +317,8 @@ type view struct {
|
||||
rxFrames, rxGot uint64
|
||||
lost, late uint64
|
||||
crc, badMagic uint64
|
||||
kdrop, errors uint64
|
||||
kdrop, link uint64
|
||||
errors uint64
|
||||
cable cableView
|
||||
}
|
||||
|
||||
@@ -334,7 +338,12 @@ func (d *direction) counters(now sample) view {
|
||||
kdrop: d.drops - d.dropBase,
|
||||
cable: d.cable.view(),
|
||||
}
|
||||
v.errors = v.lost + v.crc + v.badMagic + (now.badLen - b.badLen) + v.kdrop
|
||||
// A frame the stack refused and a frame the driver dropped are the same
|
||||
// failure seen from either side of the ring, and never the same frame twice:
|
||||
// a send that fails never reaches the driver to be dropped.
|
||||
v.link = d.nicNow - d.nicBase +
|
||||
(now.txErrs - b.txErrs) + (now.rxErrs - b.rxErrs)
|
||||
v.errors = v.lost + v.crc + v.badMagic + (now.badLen - b.badLen) + v.kdrop + v.link
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -398,25 +407,19 @@ func (d *direction) row(elapsed time.Duration, v view, target float64, length st
|
||||
statusCell(v.crc),
|
||||
statusCell(v.badMagic),
|
||||
statusCell(v.kdrop),
|
||||
statusCell(v.link),
|
||||
statusCell(v.errors),
|
||||
paint(v.cable.minText(), cCyan),
|
||||
paint(length, cCyan),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *direction) reportNIC() []string {
|
||||
// Read once a second rather than per frame, since these are sysfs files; the
|
||||
// display uses whatever the last sample left behind.
|
||||
func (d *direction) sampleNIC() {
|
||||
tx := readNIC(d.tx.name)
|
||||
rx := readNIC(d.rx.name)
|
||||
var parts []string
|
||||
if s := tx.diff(d.nicTX); s != "" {
|
||||
parts = append(parts, paint(" ▲ "+d.tx.name+" tx-side: "+s, cYellow))
|
||||
}
|
||||
if s := rx.diff(d.nicRX); s != "" {
|
||||
parts = append(parts, paint(" ▲ "+d.rx.name+" rx-side: "+s, cYellow))
|
||||
}
|
||||
d.nicTX = tx
|
||||
d.nicRX = rx
|
||||
return parts
|
||||
d.nicNow = tx.tx + rx.rx + tx.carrierDown
|
||||
}
|
||||
|
||||
func buildDirection(label string, tx, rx endpoint, patIdx int, sizes []int, cfg config) (*direction, error) {
|
||||
@@ -426,10 +429,8 @@ func buildDirection(label string, tx, rx endpoint, patIdx int, sizes []int, cfg
|
||||
tx: tx,
|
||||
rx: rx,
|
||||
streams: newLossWindows(cfg.streams),
|
||||
reports: make(chan string, 64),
|
||||
cable: newCableStats(),
|
||||
}
|
||||
d.nicTX = readNIC(tx.name)
|
||||
d.nicRX = readNIC(rx.name)
|
||||
|
||||
for i := 0; i < cfg.streams; i++ {
|
||||
et := uint16(etherBase + i)
|
||||
@@ -453,7 +454,6 @@ func buildDirection(label string, tx, rx endpoint, patIdx int, sizes []int, cfg
|
||||
// The probe carries its own ethertype so it lands on a socket of its own, but
|
||||
// it is left unsteered: it is a few frames a second and does not need a queue
|
||||
// to itself, and the stamps are taken at the wire either way.
|
||||
d.cable = newCableStats()
|
||||
d.probeSpec = newFrameSpec(patIdx, rx.mac, tx.mac, cfg.probeEther, []int{probeSize})
|
||||
fd, err := openTxSocket(tx.idx)
|
||||
if err != nil {
|
||||
@@ -471,6 +471,10 @@ func buildDirection(label string, tx, rx endpoint, patIdx int, sizes []int, cfg
|
||||
return nil, fmt.Errorf("%s probe rx timestamps: %w", label, err)
|
||||
}
|
||||
d.probeRxFD = fd
|
||||
|
||||
// Whatever the interfaces have counted before now is not ours.
|
||||
d.sampleNIC()
|
||||
d.nicBase = d.nicNow
|
||||
return d, nil
|
||||
}
|
||||
|
||||
@@ -497,7 +501,6 @@ func (d *direction) start(wg *sync.WaitGroup, doneTx, doneRx *atomic.Bool, cfg c
|
||||
spec: d.specs[i],
|
||||
stats: d.rxStats[i],
|
||||
streams: d.streams,
|
||||
reports: d.reports,
|
||||
ready: rxReady,
|
||||
}
|
||||
wg.Add(1)
|
||||
@@ -762,6 +765,7 @@ func run(aName, bName, sizesArg, patArg string,
|
||||
// Length needs both directions, so every row is sampled before any of
|
||||
// them is printed.
|
||||
for i, d := range dirs {
|
||||
d.sampleNIC()
|
||||
rows[i] = d.view(&d.prevConsole, secs)
|
||||
}
|
||||
length := "-"
|
||||
@@ -772,18 +776,6 @@ func run(aName, bName, sizesArg, patArg string,
|
||||
for _, line := range stats.emit(d.row(elapsed, rows[i], target, length)) {
|
||||
fmt.Println(line)
|
||||
}
|
||||
for _, line := range d.reportNIC() {
|
||||
fmt.Println(line)
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case msg := <-d.reports:
|
||||
fmt.Println(paint(" ✗ "+d.short+": "+msg, cRed))
|
||||
continue
|
||||
default:
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user