From cec868bf087ac2ed6dc655e4de72741ffabe7498 Mon Sep 17 00:00:00 2001 From: Felix Maurer Date: Thu, 16 May 2019 14:12:29 +0200 Subject: [PATCH 1/4] Update gosnmp The new version of gosnmp does have support for SNMP over TCP. --- Gopkg.lock | 14 +++++++++++--- Gopkg.toml | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 76c5deb62229b..54931d7e633af 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -488,6 +488,14 @@ revision = "636bf0302bc95575d69441b25a2603156ffdddf1" version = "v1.1.1" +[[projects]] + digest = "1:530233672f656641b365f8efb38ed9fba80e420baff2ce87633813ab3755ed6d" + name = "github.com/golang/mock" + packages = ["gomock"] + pruneopts = "" + revision = "51421b967af1f557f93a59e0057aaf15ca02e29c" + version = "v1.2.0" + [[projects]] digest = "1:f958a1c137db276e52f0b50efee41a1a389dcdded59a69711f3e872757dab34b" name = "github.com/golang/protobuf" @@ -1042,12 +1050,12 @@ version = "v1.0.5" [[projects]] - branch = "master" - digest = "1:4b0cabe65ca903a7b2a3e6272c5304eb788ce196d35ecb901c6563e5e7582443" + digest = "1:a1cb5e999ad98b9838147e11ed1bdb000e750ee8872e2e21c74d9464cc9110c0" name = "github.com/soniah/gosnmp" packages = ["."] pruneopts = "" - revision = "96b86229e9b3ffb4b954144cdc7f98fe3ee1003f" + revision = "40eae407a1f8cbbe3f3f14c57bde0b16db1cfe85" + version = "v1.22.0" [[projects]] branch = "master" diff --git a/Gopkg.toml b/Gopkg.toml index 4e50eb11be019..a65fcabca1f64 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -156,7 +156,7 @@ [[constraint]] name = "github.com/soniah/gosnmp" - branch = "master" + version = "1.22.0" [[constraint]] name = "github.com/StackExchange/wmi" From 85dd00fd3e2968b578f78465aabbc8880e948487 Mon Sep 17 00:00:00 2001 From: Felix Maurer Date: Thu, 16 May 2019 14:12:39 +0200 Subject: [PATCH 2/4] Add support for tcp agents to inputs.snmp Agents prefixed with 'tcp://' do now get their transport protocol set to TCP. gosnmp handles all the details. --- plugins/inputs/snmp/snmp.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/inputs/snmp/snmp.go b/plugins/inputs/snmp/snmp.go index 24250c22aac39..7a163cbb6d6ea 100644 --- a/plugins/inputs/snmp/snmp.go +++ b/plugins/inputs/snmp/snmp.go @@ -623,6 +623,10 @@ func (s *Snmp) getConnection(idx int) (snmpConnection, error) { gs := gosnmpWrapper{&gosnmp.GoSNMP{}} s.connectionCache[idx] = gs + if strings.HasPrefix(agent, "tcp://") { + agent = strings.TrimPrefix(agent, "tcp://") + gs.Transport = "tcp" + } host, portStr, err := net.SplitHostPort(agent) if err != nil { if err, ok := err.(*net.AddrError); !ok || err.Err != "missing port in address" { From b32d486b6440e7df7c7a8bbf41119e16d708f42a Mon Sep 17 00:00:00 2001 From: Felix Maurer Date: Fri, 17 May 2019 10:37:10 +0200 Subject: [PATCH 3/4] Add test for SNMP over TCP connection setup Add a new test to verify that agents prefixed with tcp: use the correct transport protocol. As getConnection does the full connection setup, we need a server listening on the port to allow the test to pass. This server is therefore also set up in the test. Also verify that the other agents still use UDP. --- plugins/inputs/snmp/snmp_test.go | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/plugins/inputs/snmp/snmp_test.go b/plugins/inputs/snmp/snmp_test.go index db1a49605df05..efa426845804b 100644 --- a/plugins/inputs/snmp/snmp_test.go +++ b/plugins/inputs/snmp/snmp_test.go @@ -272,12 +272,46 @@ func TestGetSNMPConnection_v2(t *testing.T) { assert.EqualValues(t, 567, gs.Port) assert.Equal(t, gosnmp.Version2c, gs.Version) assert.Equal(t, "foo", gs.Community) + assert.Equal(t, "udp", gs.Transport) gsc, err = s.getConnection(1) require.NoError(t, err) gs = gsc.(gosnmpWrapper) assert.Equal(t, "1.2.3.4", gs.Target) assert.EqualValues(t, 161, gs.Port) + assert.Equal(t, "udp", gs.Transport) +} + +func TestGetSNMPConnectionTCP(t *testing.T) { + var wg sync.WaitGroup + wg.Add(1) + go stubTCPServer(&wg) + wg.Wait() + + s := &Snmp{ + Agents: []string{"tcp://127.0.0.1:56789"}, + } + err := s.init() + require.NoError(t, err) + + wg.Add(1) + gsc, err := s.getConnection(0) + require.NoError(t, err) + gs := gsc.(gosnmpWrapper) + assert.Equal(t, "127.0.0.1", gs.Target) + assert.EqualValues(t, 56789, gs.Port) + assert.Equal(t, "tcp", gs.Transport) + wg.Wait() +} + +func stubTCPServer(wg *sync.WaitGroup) { + defer wg.Done() + tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:56789") + tcpServer, _ := net.ListenTCP("tcp", tcpAddr) + defer tcpServer.Close() + wg.Done() + conn, _ := tcpServer.AcceptTCP() + defer conn.Close() } func TestGetSNMPConnection_v3(t *testing.T) { From 8dd01c9edafdd927af8e39942d00fb2636f40ca8 Mon Sep 17 00:00:00 2001 From: Felix Maurer Date: Fri, 17 May 2019 10:42:26 +0200 Subject: [PATCH 4/4] Update README for SNMP over TCP --- plugins/inputs/snmp/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/inputs/snmp/README.md b/plugins/inputs/snmp/README.md index dab28e9b0a976..a15e5ddb6a5e1 100644 --- a/plugins/inputs/snmp/README.md +++ b/plugins/inputs/snmp/README.md @@ -98,7 +98,7 @@ Resulting output: ### Config parameters * `agents`: Default: `[]` -List of SNMP agents to connect to in the form of `IP[:PORT]`. If `:PORT` is unspecified, it defaults to `161`. +List of SNMP agents to connect to in the form of `[tcp://]IP[:PORT]`. If `:PORT` is unspecified, it defaults to `161`. When using the optional prefix `tcp://`, SNMP over TCP will be used. Otherwise UDP is used as the transport protocol. * `version`: Default: `2` SNMP protocol version to use.