mirror of https://github.com/vishvananda/netlink
Parse link statistics (#118)
Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
parent
ef0e63f64d
commit
339261d114
30
link.go
30
link.go
|
@ -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 {
|
||||
|
|
|
@ -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]))
|
||||
}
|
||||
|
|
48
link_test.go
48
link_test.go
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue