From dfff8af4df44e0840e963bccec68370edb5bc4a2 Mon Sep 17 00:00:00 2001 From: James Lamb Date: Mon, 7 Dec 2015 16:56:02 +1100 Subject: [PATCH 1/4] add nf_conntrack statistics to net_linux to query iptables/netfilter conntrack limits --- .gitignore | 3 ++- net/net.go | 5 +++++ net/net_linux.go | 30 ++++++++++++++++++++++++++++++ net/net_test.go | 20 ++++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 194eab89..d2b87e8e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *~ #* _obj -*.tmp \ No newline at end of file +*.tmp +.idea diff --git a/net/net.go b/net/net.go index 61f9abf0..22533102 100644 --- a/net/net.go +++ b/net/net.go @@ -64,6 +64,11 @@ type NetInterfaceStat struct { Addrs []NetInterfaceAddr `json:"addrs"` } +type NetFilterStat struct { + ConnTrackCount int32 `json:"conntrackcount"` + ConnTrackMax int32 `json:"conntrackmax"` +} + var constMap = map[string]int{ "TCP": syscall.SOCK_STREAM, "UDP": syscall.SOCK_DGRAM, diff --git a/net/net_linux.go b/net/net_linux.go index 51d80913..b12a8fc7 100644 --- a/net/net_linux.go +++ b/net/net_linux.go @@ -160,3 +160,33 @@ func NetProtoCounters(protocols []string) ([]NetProtoCountersStat, error) { } return stats, nil } + +// NetFilterCounters returns iptables conntrack statistics +// the currently in use conntrack count and the max. +// If the file does not exist or is invalid it will return nil. +func NetFilterCounters() (NetFilterStat, error) { + countfile := "/proc/sys/net/netfilter/nf_conntrack_count" + count, err := common.ReadLines(count) + if err != nil { + return nil, err + } + + maxfile := "/proc/sys/net/netfilter/nf_conntrack_max" + max, err := common.ReadLines(maxfile) + if err != nil { + return nil, err + } + if len(count) != 1 { + // format of file has changed + return nil, err + } + if len(max) != 1 { + // format of file has changed + return nil, err + } + stats := NetFilterStat{ + ConnTrackCount: count, + ConnTrackMax: max, + } + return stats, nil +} diff --git a/net/net_test.go b/net/net_test.go index 187c320d..0bac45fe 100644 --- a/net/net_test.go +++ b/net/net_test.go @@ -196,3 +196,23 @@ func TestNetConnections(t *testing.T) { } } + +func TestNetFilterCounters(t *testing.T) { + if ci := os.Getenv("CI"); ci != "" { // skip if test on drone.io + return + } + + v, err := NetFilterCounters() + if err != nil { + t.Errorf("could not get NetConnections: %v", err) + } + if len(v) == 0 { + t.Errorf("could not get NetConnections: %v", v) + } + for _, vv := range v { + if vv.ConnTrackMax == 0 { + t.Errorf("nf_conntrack_max needs to be greater than zero: %v", vv) + } + } + +} From 22f35fd518c9944bbe084ddf11a52fa2670c2251 Mon Sep 17 00:00:00 2001 From: James Lamb Date: Tue, 8 Dec 2015 09:32:45 +1100 Subject: [PATCH 2/4] add netfilter counter support --- internal/common/common.go | 27 +++++++++++++++++++++++++++ net/net.go | 4 ++-- net/net_linux.go | 34 ++++++++++++++++------------------ 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/internal/common/common.go b/internal/common/common.go index aeadda6b..3449cdd0 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -141,6 +141,33 @@ func ByteToString(orig []byte) string { return string(orig[l:n]) } +// ReadInts reads contents from single line file and returns them as []int32. +func ReadInts(filename string) ([]int64, error) { + f, err := os.Open(filename) + if err != nil { + return []int64{}, err + } + defer f.Close() + + var ret []int64 + + r := bufio.NewReader(f) + + // The int files that this is concerned with should only be one liners. + line, err := r.ReadString('\n') + if err != nil { + return []int64{}, err + } + + i, err := strconv.ParseInt(strings.Trim(line, "\n"), 10, 32) + if err != nil { + return []int64{}, err + } + ret = append(ret, i) + + return ret, nil +} + // Parse to int32 without error func mustParseInt32(val string) int32 { vv, _ := strconv.ParseInt(val, 10, 32) diff --git a/net/net.go b/net/net.go index 22533102..feb5c388 100644 --- a/net/net.go +++ b/net/net.go @@ -65,8 +65,8 @@ type NetInterfaceStat struct { } type NetFilterStat struct { - ConnTrackCount int32 `json:"conntrackcount"` - ConnTrackMax int32 `json:"conntrackmax"` + ConnTrackCount int64 `json:"conntrackcount"` + ConnTrackMax int64 `json:"conntrackmax"` } var constMap = map[string]int{ diff --git a/net/net_linux.go b/net/net_linux.go index b12a8fc7..058720a0 100644 --- a/net/net_linux.go +++ b/net/net_linux.go @@ -164,29 +164,27 @@ func NetProtoCounters(protocols []string) ([]NetProtoCountersStat, error) { // NetFilterCounters returns iptables conntrack statistics // the currently in use conntrack count and the max. // If the file does not exist or is invalid it will return nil. -func NetFilterCounters() (NetFilterStat, error) { +func NetFilterCounters() ([]NetFilterStat, error) { countfile := "/proc/sys/net/netfilter/nf_conntrack_count" - count, err := common.ReadLines(count) + maxfile := "/proc/sys/net/netfilter/nf_conntrack_max" + + count, err := common.ReadInts(countfile) + + if err != nil { + return nil, err + } + stats := make([]NetFilterStat, 0, 1) + + max, err := common.ReadInts(maxfile) if err != nil { return nil, err } - maxfile := "/proc/sys/net/netfilter/nf_conntrack_max" - max, err := common.ReadLines(maxfile) - if err != nil { - return nil, err - } - if len(count) != 1 { - // format of file has changed - return nil, err - } - if len(max) != 1 { - // format of file has changed - return nil, err - } - stats := NetFilterStat{ - ConnTrackCount: count, - ConnTrackMax: max, + payload := NetFilterStat{ + ConnTrackCount: count[0], + ConnTrackMax: max[0], } + + stats = append(stats, payload) return stats, nil } From 5700150054524bec4ad004a9a73039662324ce53 Mon Sep 17 00:00:00 2001 From: James Lamb Date: Wed, 9 Dec 2015 07:45:26 +1100 Subject: [PATCH 3/4] Updated README.rst and included updated syntax to be more uniform with the other code --- README.rst | 6 ++++++ net/net.go | 4 ++-- net/net_linux.go | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 20fae2a6..485d71e6 100644 --- a/README.rst +++ b/README.rst @@ -124,6 +124,11 @@ Several methods have been added which are not present in psutil, but will provid - system wide stats on network protocols (i.e IP, TCP, UDP, etc.) - sourced from /proc/net/snmp +- iptables nf_conntrack (linux only) + + - system wide stats on netfilter conntrack module + - sourced from /proc/sys/net/netfilter/nf_conntrack_count + Some codes are ported from Ohai. many thanks. @@ -153,6 +158,7 @@ net_connections x x net_protocols x net_if_addrs net_if_stats +netfilter_conntrack x ================= ====== ======= ====== ======= Process class diff --git a/net/net.go b/net/net.go index feb5c388..addb4481 100644 --- a/net/net.go +++ b/net/net.go @@ -65,8 +65,8 @@ type NetInterfaceStat struct { } type NetFilterStat struct { - ConnTrackCount int64 `json:"conntrackcount"` - ConnTrackMax int64 `json:"conntrackmax"` + ConnTrackCount int64 `json:"conn_track_count"` + ConnTrackMax int64 `json:"conn_track_max"` } var constMap = map[string]int{ diff --git a/net/net_linux.go b/net/net_linux.go index 058720a0..9e2d7403 100644 --- a/net/net_linux.go +++ b/net/net_linux.go @@ -165,8 +165,8 @@ func NetProtoCounters(protocols []string) ([]NetProtoCountersStat, error) { // the currently in use conntrack count and the max. // If the file does not exist or is invalid it will return nil. func NetFilterCounters() ([]NetFilterStat, error) { - countfile := "/proc/sys/net/netfilter/nf_conntrack_count" - maxfile := "/proc/sys/net/netfilter/nf_conntrack_max" + countfile := common.HostProc("sys/net/netfilter/nf_conntrack_count") + maxfile := common.HostProc("sys/net/netfilter/nf_conntrack_max") count, err := common.ReadInts(countfile) From a9e946c7dd9a830ceb183aed7f8eec35d757e56a Mon Sep 17 00:00:00 2001 From: James Lamb Date: Wed, 9 Dec 2015 07:49:20 +1100 Subject: [PATCH 4/4] change the snakecase to reflect the files being read --- net/net.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/net.go b/net/net.go index addb4481..66d5991b 100644 --- a/net/net.go +++ b/net/net.go @@ -65,8 +65,8 @@ type NetInterfaceStat struct { } type NetFilterStat struct { - ConnTrackCount int64 `json:"conn_track_count"` - ConnTrackMax int64 `json:"conn_track_max"` + ConnTrackCount int64 `json:"conntrack_count"` + ConnTrackMax int64 `json:"conntrack_max"` } var constMap = map[string]int{