Parse link statistics (#118)

Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
Alessandro Boch 2016-05-12 10:53:32 -07:00 committed by Vish Ishaya
parent ef0e63f64d
commit 339261d114
3 changed files with 86 additions and 0 deletions

30
link.go
View File

@ -31,6 +31,7 @@ type LinkAttrs struct {
MasterIndex int // must be the index of a bridge
Namespace interface{} // nil | NsPid | NsFd
Alias string
Statistics *LinkStatistics
}
// NewLinkAttrs returns LinkAttrs structure filled with default values
@ -40,6 +41,35 @@ func NewLinkAttrs() LinkAttrs {
}
}
/*
Ref: struct rtnl_link_stats {...}
*/
type LinkStatistics struct {
RxPackets uint32
TxPackets uint32
RxBytes uint32
TxBytes uint32
RxErrors uint32
TxErrors uint32
RxDropped uint32
TxDropped uint32
Multicast uint32
Collisions uint32
RxLengthErrors uint32
RxOverErrors uint32
RxCrcErrors uint32
RxFrameErrors uint32
RxFifoErrors uint32
RxMissedErrors uint32
TxAbortedErrors uint32
TxCarrierErrors uint32
TxFifoErrors uint32
TxHeartbeatErrors uint32
TxWindowErrors uint32
RxCompressed uint32
TxCompressed uint32
}
// Device links cannot be created via netlink. These links
// are links created by udev like 'lo' and 'etho0'
type Device struct {

View File

@ -12,6 +12,8 @@ import (
"github.com/vishvananda/netlink/nl"
)
const SizeofLinkStats = 0x5c
var native = nl.NativeEndian()
var lookupByDump = false
@ -943,6 +945,8 @@ func linkDeserialize(m []byte) (Link, error) {
base.TxQLen = int(native.Uint32(attr.Value[0:4]))
case syscall.IFLA_IFALIAS:
base.Alias = string(attr.Value[:len(attr.Value)-1])
case syscall.IFLA_STATS:
base.Statistics = parseLinkStats(attr.Value[:])
}
}
// Links that don't have IFLA_INFO_KIND are hardware devices
@ -1360,3 +1364,7 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
}
func parseLinkStats(data []byte) *LinkStatistics {
return (*LinkStatistics)(unsafe.Pointer(&data[0:SizeofLinkStats][0]))
}

View File

@ -779,3 +779,51 @@ func TestLinkSubscribe(t *testing.T) {
t.Fatal("Del update not received as expected")
}
}
func TestLinkStats(t *testing.T) {
defer setUpNetlinkTest(t)()
// Create a veth pair and verify the cross-stats once both
// ends are brought up and some ICMPv6 packets are exchanged
v0 := "v0"
v1 := "v1"
vethLink := &Veth{LinkAttrs: LinkAttrs{Name: v0}, PeerName: v1}
if err := LinkAdd(vethLink); err != nil {
t.Fatal(err)
}
veth0, err := LinkByName(v0)
if err != nil {
t.Fatal(err)
}
if err := LinkSetUp(veth0); err != nil {
t.Fatal(err)
}
veth1, err := LinkByName(v1)
if err != nil {
t.Fatal(err)
}
if err := LinkSetUp(veth1); err != nil {
t.Fatal(err)
}
time.Sleep(2 * time.Second)
// verify statistics
veth0, err = LinkByName(v0)
if err != nil {
t.Fatal(err)
}
veth1, err = LinkByName(v1)
if err != nil {
t.Fatal(err)
}
v0Stats := veth0.Attrs().Statistics
v1Stats := veth1.Attrs().Statistics
if v0Stats.RxPackets != v1Stats.TxPackets || v0Stats.TxPackets != v1Stats.RxPackets ||
v0Stats.RxBytes != v1Stats.TxBytes || v0Stats.TxBytes != v1Stats.RxBytes {
t.Fatalf("veth ends counters differ:\n%v\n%v", v0Stats, v1Stats)
}
}