Collapse errors into lost, corrupt, link and internal
This commit is contained in:
@@ -94,24 +94,25 @@ func (d *direction) capture(t time.Time) counterSet {
|
|||||||
return counterSet{t: t, s: d.snapshot(), drops: d.drops, nic: d.nic.Load()}
|
return counterSet{t: t, s: d.snapshot(), drops: d.drops, nic: d.nic.Load()}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Late is counted but left out of the total, since a reordered frame arrived.
|
// What someone testing a cable is asking, rather than how each failure happened
|
||||||
|
// to be noticed. Corruption arrives as three different symptoms and the kernel
|
||||||
|
// drops frames for reasons that are ours rather than the cable's, but none of
|
||||||
|
// that is a distinction worth reading off a panel.
|
||||||
type errs struct {
|
type errs struct {
|
||||||
lost, late uint64
|
lost uint64
|
||||||
crc, badMagic uint64
|
corrupt uint64
|
||||||
badLen uint64
|
link uint64
|
||||||
kdrop, link uint64
|
internal uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e errs) total() uint64 {
|
func (e errs) total() uint64 {
|
||||||
return e.lost + e.crc + e.badMagic + e.badLen + e.kdrop + e.link
|
return e.lost + e.corrupt + e.link + e.internal
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e errs) add(o errs) errs {
|
func (e errs) add(o errs) errs {
|
||||||
return errs{
|
return errs{
|
||||||
lost: e.lost + o.lost, late: e.late + o.late,
|
lost: e.lost + o.lost, corrupt: e.corrupt + o.corrupt,
|
||||||
crc: e.crc + o.crc, badMagic: e.badMagic + o.badMagic,
|
link: e.link + o.link, internal: e.internal + o.internal,
|
||||||
badLen: e.badLen + o.badLen,
|
|
||||||
kdrop: e.kdrop + o.kdrop, link: e.link + o.link,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,11 +310,9 @@ var intervalCols = []colSpec{
|
|||||||
{title: "RX pps", width: 9, right: true},
|
{title: "RX pps", width: 9, right: true},
|
||||||
{title: "RX Gb/s", width: 7, right: true},
|
{title: "RX Gb/s", width: 7, right: true},
|
||||||
{title: "LOST", width: 11, right: true},
|
{title: "LOST", width: 11, right: true},
|
||||||
{title: "LATE", width: 9, right: true},
|
{title: "CORRUPT", width: 11, right: true},
|
||||||
{title: "CRC", width: 7, right: true},
|
{title: "LINK", width: 11, right: true},
|
||||||
{title: "BADMAG", width: 7, right: true},
|
{title: "INTERNAL", width: 11, right: true},
|
||||||
{title: "KDROP", width: 11, right: true},
|
|
||||||
{title: "LINK", width: 13, right: true},
|
|
||||||
{title: "ERRORS", width: 13, right: true},
|
{title: "ERRORS", width: 13, right: true},
|
||||||
{title: "MIN ns", width: 9, right: true},
|
{title: "MIN ns", width: 9, right: true},
|
||||||
{title: "LEN m", width: 6, right: true},
|
{title: "LEN m", width: 6, right: true},
|
||||||
@@ -332,16 +331,21 @@ type view struct {
|
|||||||
|
|
||||||
func errsBetween(b, n counterSet) errs {
|
func errsBetween(b, n counterSet) errs {
|
||||||
return errs{
|
return errs{
|
||||||
lost: n.s.lost - b.s.lost,
|
lost: n.s.lost - b.s.lost,
|
||||||
late: n.s.late - b.s.late,
|
// Three ways of noticing one thing: a payload that does not match its
|
||||||
crc: n.s.crcErr - b.s.crcErr,
|
// checksum, a header that is not ours, and a length that cannot be.
|
||||||
badMagic: n.s.badMagic - b.s.badMagic,
|
corrupt: (n.s.crcErr - b.s.crcErr) + (n.s.badMagic - b.s.badMagic) +
|
||||||
badLen: n.s.badLen - b.s.badLen,
|
(n.s.badLen - b.s.badLen),
|
||||||
kdrop: n.drops - b.drops,
|
|
||||||
// A frame the stack refused and a frame the driver dropped are the same
|
// 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
|
// 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.
|
// twice: a send that fails never reaches the driver to be dropped.
|
||||||
link: (n.nic - b.nic) + (n.s.txErrs - b.s.txErrs) + (n.s.rxErrs - b.s.rxErrs),
|
link: (n.nic - b.nic) + (n.s.txErrs - b.s.txErrs) + (n.s.rxErrs - b.s.rxErrs),
|
||||||
|
// Ours rather than the cable's: frames the kernel threw away because we
|
||||||
|
// did not drain the ring fast enough, and frames so far out of order
|
||||||
|
// that our own bookkeeping had already written them off. The second is
|
||||||
|
// unreachable while each stream has a flow rule to its own queue, which
|
||||||
|
// is exactly why it is worth counting: it fires if that stops holding.
|
||||||
|
internal: (n.drops - b.drops) + (n.s.late - b.s.late),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,11 +437,9 @@ func (d *direction) row(elapsed time.Duration, v view, target float64, length st
|
|||||||
commas(uint64(v.rxPPS)),
|
commas(uint64(v.rxPPS)),
|
||||||
rateCell(v.rxGbps, target),
|
rateCell(v.rxGbps, target),
|
||||||
statusCell(v.since.lost),
|
statusCell(v.since.lost),
|
||||||
statusCell(v.since.late),
|
statusCell(v.since.corrupt),
|
||||||
statusCell(v.since.crc),
|
|
||||||
statusCell(v.since.badMagic),
|
|
||||||
statusCell(v.since.kdrop),
|
|
||||||
statusCell(v.since.link),
|
statusCell(v.since.link),
|
||||||
|
statusCell(v.since.internal),
|
||||||
statusCell(v.since.total()),
|
statusCell(v.since.total()),
|
||||||
paint(v.cable.minText(), cCyan),
|
paint(v.cable.minText(), cCyan),
|
||||||
paint(length, cCyan),
|
paint(length, cCyan),
|
||||||
|
|||||||
@@ -195,12 +195,9 @@ var errRows = []struct {
|
|||||||
get func(errs) uint64
|
get func(errs) uint64
|
||||||
}{
|
}{
|
||||||
{"lost", func(e errs) uint64 { return e.lost }},
|
{"lost", func(e errs) uint64 { return e.lost }},
|
||||||
{"late", func(e errs) uint64 { return e.late }},
|
{"corrupt", func(e errs) uint64 { return e.corrupt }},
|
||||||
{"crc", func(e errs) uint64 { return e.crc }},
|
|
||||||
{"bad magic", func(e errs) uint64 { return e.badMagic }},
|
|
||||||
{"bad length", func(e errs) uint64 { return e.badLen }},
|
|
||||||
{"kernel drops", func(e errs) uint64 { return e.kdrop }},
|
|
||||||
{"link", func(e errs) uint64 { return e.link }},
|
{"link", func(e errs) uint64 { return e.link }},
|
||||||
|
{"internal", func(e errs) uint64 { return e.internal }},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *display) errBlock(x, w, y int, e errs) int {
|
func (d *display) errBlock(x, w, y int, e errs) int {
|
||||||
|
|||||||
Reference in New Issue
Block a user