diff --git a/net_softnet.go b/net_softnet.go index a94f86dc..06b7b8f2 100644 --- a/net_softnet.go +++ b/net_softnet.go @@ -27,8 +27,9 @@ import ( // For the proc file format details, // See: // * Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2343 -// * Linux 4.17 https://elixir.bootlin.com/linux/v4.17/source/net/core/net-procfs.c#L162 -// and https://elixir.bootlin.com/linux/v4.17/source/include/linux/netdevice.h#L2810. +// * Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086 +// * Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162 +// * Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169 // SoftnetStat contains a single row of data from /proc/net/softnet_stat. type SoftnetStat struct { @@ -38,6 +39,18 @@ type SoftnetStat struct { Dropped uint32 // Number of times processing packets ran out of quota. TimeSqueezed uint32 + // Number of collision occur while obtaining device lock while transmitting. + CPUCollision uint32 + // Number of times cpu woken up received_rps. + ReceivedRps uint32 + // number of times flow limit has been reached. + FlowLimitCount uint32 + // Softnet backlog status. + SoftnetBacklogLen uint32 + // CPU id owning this softnet_data. + Index uint32 + // softnet_data's Width. + Width int } var softNetProcFile = "net/softnet_stat" @@ -66,22 +79,57 @@ func parseSoftnet(r io.Reader) ([]SoftnetStat, error) { for s.Scan() { columns := strings.Fields(s.Text()) width := len(columns) + softnetStat := SoftnetStat{} if width < minColumns { return nil, fmt.Errorf("%d columns were detected, but at least %d were expected", width, minColumns) } - // We only parse the first three columns at the moment. - us, err := parseHexUint32s(columns[0:3]) - if err != nil { - return nil, err + // Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2347 + if width >= minColumns { + us, err := parseHexUint32s(columns[0:9]) + if err != nil { + return nil, err + } + + softnetStat.Processed = us[0] + softnetStat.Dropped = us[1] + softnetStat.TimeSqueezed = us[2] + softnetStat.CPUCollision = us[8] + } + + // Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086 + if width >= 10 { + us, err := parseHexUint32s(columns[9:10]) + if err != nil { + return nil, err + } + + softnetStat.ReceivedRps = us[0] } - stats = append(stats, SoftnetStat{ - Processed: us[0], - Dropped: us[1], - TimeSqueezed: us[2], - }) + // Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162 + if width >= 11 { + us, err := parseHexUint32s(columns[10:11]) + if err != nil { + return nil, err + } + + softnetStat.FlowLimitCount = us[0] + } + + // Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169 + if width >= 13 { + us, err := parseHexUint32s(columns[11:13]) + if err != nil { + return nil, err + } + + softnetStat.SoftnetBacklogLen = us[0] + softnetStat.Index = us[1] + } + softnetStat.Width = width + stats = append(stats, softnetStat) } return stats, nil diff --git a/net_softnet_test.go b/net_softnet_test.go index f25e09f3..1620c86b 100644 --- a/net_softnet_test.go +++ b/net_softnet_test.go @@ -25,15 +25,54 @@ func TestNetSoftnet(t *testing.T) { t.Fatal(err) } - want := []SoftnetStat{{ - Processed: 0x00015c73, - Dropped: 0x00020e76, - TimeSqueezed: 0xf0000769, - }, + want := []SoftnetStat{ + { + Processed: 0x00358fe3, + Dropped: 0x00006283, + TimeSqueezed: 0x00000000, + CPUCollision: 0x00000000, + ReceivedRps: 0x000855fc, + FlowLimitCount: 0x00000076, + SoftnetBacklogLen: 0x00000000, + Index: 0x00000000, + Width: 13, + }, + { + Processed: 0x00953d1a, + Dropped: 0x00000446, + TimeSqueezed: 0x000000b1, + CPUCollision: 0x00000000, + ReceivedRps: 0x008eeb9a, + FlowLimitCount: 0x0000002b, + SoftnetBacklogLen: 0x000000dc, + Index: 0x00000001, + Width: 13, + }, + { + Processed: 0x00015c73, + Dropped: 0x00020e76, + TimeSqueezed: 0xf0000769, + CPUCollision: 0x00000004, + ReceivedRps: 0x00000003, + FlowLimitCount: 0x00000002, + Width: 11, + }, { Processed: 0x01663fb2, + Dropped: 0x00000000, TimeSqueezed: 0x0109a4, - }} + CPUCollision: 0x00020e76, + Width: 9, + }, + { + Processed: 0x00008e78, + Dropped: 0x00000001, + TimeSqueezed: 0x00000011, + CPUCollision: 0x00000020, + ReceivedRps: 0x00000010, + Width: 10, + }, + } got, err := fs.NetSoftnetStat() if err != nil { diff --git a/testdata/fixtures.ttar b/testdata/fixtures.ttar index 53c45d70..a965b110 100644 --- a/testdata/fixtures.ttar +++ b/testdata/fixtures.ttar @@ -2482,9 +2482,12 @@ FRAG6: inuse 0 memory 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/softnet_stat -Lines: 2 -00015c73 00020e76 F0000769 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 -01663fb2 00000000 000109a4 00000000 00000000 00000000 00000000 00000000 00000000 +Lines: 5 +00358fe3 00006283 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000855fc 00000076 00000000 00000000 +00953d1a 00000446 000000b1 00000000 00000000 00000000 00000000 00000000 00000000 008eeb9a 0000002b 000000dc 00000001 +00015c73 00020e76 f0000769 00000000 00000000 00000000 00000000 00000000 00000004 00000003 00000002 +01663fb2 00000000 000109a4 00000000 00000000 00000000 00000000 00000000 00020e76 +00008e78 00000001 00000011 00000000 00000000 00000000 00000000 00000000 00000020 00000010 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/softnet_stat.broken