📜 ⬆️ ⬇️

Why is SNMP not so easy?

A long time ago, on Habré, an article was published telling how to use a popular library to work with SNMP from a Java application. Supporting, in general, the author's initiative, I want to dwell on the difficulties that may arise in a real project using SNMP.

We read documentation


For a start, I would like to dwell on the fact that I don’t quite understand why, out of all the variety of SNMP requests, the author drew attention to TRAP? Let's see what RFC 1157 writes about this:
This is a clear concept of a strategy for the monitoring of the network. A limited number of unsolicited messages (traps) Hentay
minimizing the amount of traffic generated by the network management function.

For those who have difficulties with the English language, there is a Russian translation :

The SNMP strategy is that network status monitoring with any significant level of granularity is performed mainly by polling from the monitoring center. A limited number of unsolicited messages (trap) provides synchronization and activates polls. Limiting the number of unsolicited messages is consistent with the objectives of ensuring simplicity and minimizing traffic generated by the network management system.

From these quotes, it is quite clear that requests with TRAP and INFORM types are not the most frequently used part of SNMP. An article for beginners would be more appropriate to illustrate with examples of using much more popular GET requests.

In general, I strongly recommend that you review all SNCs related to SNMP before you begin. Some aspects of SNMP are not obvious and it makes sense to get an idea about them from the source. You can begin to get acquainted with the material from the wiki .
')

The first steps


In addition to the mandatory documentation of the documentation, it is important to understand why we do all this. In the practice of telecom, the most common tasks are:

  1. SNMP equipment survey (accounting, monitoring)
  2. SNMP equipment management (activation)

Tasks related to equipment polling are reduced to the formation of GET (and as will be shown further GETNEXT) requests. Equipment management is reduced to sending SET requests that change the state of the corresponding variables on the equipment (for example, in this way, you can turn off any interface).

The task of SNMP monitoring stands out against the general background by the requirement that the equipment being polled is either a lot or a lot. Suppose that this is exactly the task we are to solve.

Let's start writing code. In the test example, we will access our own host via SNMP and read the value of the variable specified by the OID 1.3.6.1.2.1.1.3.0 and containing the uptime value of the host:

Single GET Request
package com.acme.ae.tests.snmp; import java.io.IOException; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class Test { private final static String SNMP_COMMUNITY = "public"; private final static int SNMP_RETRIES = 3; private final static long SNMP_TIMEOUT = 1000L; private Snmp snmp = null; private TransportMapping transport = null; private void test() throws IOException { Target t = getTarget("udp:127.0.0.1/161"); String r = send(t, "1.3.6.1.2.1.1.3.0"); System.out.println(r); } private String send(Target target, String oid) throws IOException { PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID(oid))); pdu.setType(PDU.GET); ResponseEvent event = snmp.send(pdu, target, null); if (event != null) { return event.getResponse().get(0).toString(); } else { return "Timeout exceeded"; } } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version1); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String[] args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } } 


Before making sure that the SNMP service on our host is running and running the code, we’ll get the required uptime value (host non-stop since the last boot):

 1.3.6.1.2.1.1.3.0 = 2:28:55.06 

Using this value, you can monitor. If we find that the value has decreased - then the host has managed to reboot since the next poll. If the host did not respond within the specified timeout (after several automatically made attempts), this most likely means that the host is down. Is everything simple?

Counted - wept


Not really. We recall that we have to fulfill many requests. Let's measure how many requests we can perform per second? We make a small correction to the code:

  private void test() throws IOException { Target t = getTarget("udp:127.0.0.1/161"); Long timestamp = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { send(t, "1.3.6.1.2.1.1.3.0"); } System.out.println(1000000L /(System.currentTimeMillis() - timestamp)); } 

And run it for execution:

 2463 

Almost two and a half thousand requests per second! Not bad?

Let's not rush. We send requests to the Loopback interface, and it works slightly faster than the local network. Let's see how many requests per second we will have time to perform to another host on our network:

 182 

Do not even reach two hundred. Generally speaking, this may be enough. It all depends on the task. But we took measurements, provided that the polled host is available. What happens if the host does not respond?

There will be several access attempts (in our code we set 3) separated by a timeout (1000 ms). This means that in a second we will not have time to fulfill a single request. Since an unresponsive host is not such a rarity, this can be a big problem in a real project.

We go to the record


What can be done with this? If we dealt with any synchronous protocol (for example, telnet), we would not have much choice. In order to increase performance, we would have to simultaneously perform many threads. But SNMP is asynchronous in nature! No need to force it into a synchronous frame.

How to go to the asynchronous version? In our case, quite simple:

Asynchronous requests
 package com.acme.ae.tests.snmp; import java.io.IOException; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class Test implements ResponseListener { private final static String SNMP_COMMUNITY = "public"; private final static int SNMP_RETRIES = 3; private final static long SNMP_TIMEOUT = 1000L; private Snmp snmp = null; private TransportMapping transport = null; public void onResponse(ResponseEvent event) { PDU response = event.getResponse(); if (response != null) { System.out.println(response.get(0).toString()); return; } } private void test() throws IOException { Target t = getTarget("udp:192.168.131.253/161"); Long timestamp = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { send(t, "1.3.6.1.2.1.1.3.0"); } System.out.println(1000000L /(System.currentTimeMillis() - timestamp)); } private void send(Target target, String oid) throws IOException { PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID(oid))); pdu.setType(PDU.GET); snmp.send(pdu, target, null, this); } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version1); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String[] args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } } 


 7142 

Requests are like falling into a bottomless barrel! Of course, the answers will come with a delay, but they will also come pretty quickly. But how do we know that the host has not responded?

Very simply, after the specified number of attempts and timeouts, SNMP4J will return to us an event whose response will be null:

Corrected version
 package com.acme.ae.tests.snmp; import java.io.IOException; import java.util.HashSet; import java.util.Set; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class Test implements ResponseListener { private final static String SNMP_COMMUNITY = "public"; private final static int SNMP_RETRIES = 3; private final static long SNMP_TIMEOUT = 1000L; private Snmp snmp = null; private TransportMapping transport = null; private Set<Integer32> requests = new HashSet<Integer32>(); private Long firstTimestamp = null; private long lastTimestamp; public void onResponse(ResponseEvent event) { Integer32 requestId = event.getRequest().getRequestID(); PDU response = event.getResponse(); if (response != null) { lastTimestamp = System.currentTimeMillis(); if (firstTimestamp == null) { firstTimestamp = lastTimestamp; } return; } else { synchronized (requests) { if (requests.contains(requestId)) { System.out.println("Timeout exceeded"); } } } synchronized (requests) { requests.remove(requestId); } } private void test() throws IOException { Target t = getTarget("udp:192.168.131.253/161"); Long timestamp = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { send(t, "1.3.6.1.2.1.1.3.0"); } System.out.println(1000000L /(System.currentTimeMillis() - timestamp)); while (!requests.isEmpty()) { try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } } if (firstTimestamp != null) { System.out.println(1000000L /(lastTimestamp - firstTimestamp)); } } private void send(Target target, String oid) throws IOException { PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID(oid))); pdu.setType(PDU.GET); snmp.send(pdu, target, null, this); synchronized (requests) { requests.add(pdu.getRequestID()); } } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version1); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String[] args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } } 


Let's analyze the result of the execution:

 9174 283 

We manage to generate 9174 requests per second, and the polled device manages to process requests at a speed of 283 requests per second. It does not have time to respond to most of the requests (accordingly, “Timeout exceeded” messages remain in the log). Of course, this will not be a problem when we begin to poll a large number of devices with a reasonable interval between requests.

Go ahead


We learned how to get scalar variable values ​​via SNMP. But besides them, in SNMP there are also tables (for example, a table of interfaces on the device). How are they arranged? Let's look at the MIB browser:

image

In mgmt.interfaces OID (1.3.6.1.2.1.2), we see the scalar variable ifNumber (1.3.6.1.2.1.2.1), which contains the number of interfaces in the table, as well as a set of columns. Each column has its own OID. For example, a column containing the numeric index of the ifIndex interface has OID = 1.3.6.1.2.1.2.2.1.1.

In order to get the value of this variable, you must add an interface index to the OID (for example, for the interface with the index 123 OID = 1.3.6.1.2.1.2.2.1.1.123). But how do we get the interface indexes? They do not necessarily go in order! For example, on my machine, the interface table looks like this:

image

It is for this purpose that the GETNEXT request was coined. Passing the OID prefix to this query, we get the OID and the value of the next (in lexicographical order) after this variable prefix. This means that by passing the prefixes to the OIDs of the table columns, we will get the OIDs and values ​​of its first row. To get the next line, you need to execute another request, passing in it the OIDs received by the previous request. And so on until we look through the whole table.

Of course, taking into account all the above, we should minimize the number of requests (this is also necessary taking into account the fact that within one request, according to the RFC, consistent data is provided, if we request the index and interface name by two consecutive requests, they may not correspond to each other). Within the first version of SNMP, we must read the entire row of the table in one request.

It should be noted that it is rather convenient that the OIDs of scalar variables are also prefixes. For example, for the sysUpTime variable, the OID is actually 1.3.6.1.2.1.1.3. We can send it to the GETNEXT request and get the OID = 1.3.6.1.2.1.1.3.0 along with the corresponding value. This makes it possible to query the scalar values ​​along with the column values ​​of the tables, in a single query.

View the first row of the table
 package com.acme.ae.tests.snmp; import java.io.IOException; import java.util.HashSet; import java.util.Set; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class Test implements ResponseListener { private final static String SNMP_COMMUNITY = "public"; private final static int SNMP_RETRIES = 3; private final static long SNMP_TIMEOUT = 1000L; private Snmp snmp = null; private TransportMapping transport = null; private Set<Integer32> requests = new HashSet<Integer32>(); public void onResponse(ResponseEvent event) { Integer32 requestId = event.getRequest().getRequestID(); PDU response = event.getResponse(); if (response != null) { System.out.println(response.toString()); return; } else { synchronized (requests) { if (requests.contains(requestId)) { System.out.println("Timeout exceeded"); } } } synchronized (requests) { requests.remove(requestId); } } private void test() throws IOException { Target t = getTarget("udp:127.0.0.1/161"); send(t, new String[] {"1.3.6.1.2.1.1.3", "1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2"}); } private void send(Target target, String[] oids) throws IOException { PDU pdu = new PDU(); for (String oid: oids) { pdu.add(new VariableBinding(new OID(oid))); } pdu.setType(PDU.GETNEXT); ResponseEvent event = snmp.send(pdu, target, null); synchronized (requests) { requests.add(pdu.getRequestID()); } onResponse(event); } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version1); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String[] args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } } 


By running this code, we get the following response:

 RESPONSE[requestID=1170688508, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.1.3.0 = 4:50:53.72; 1.3.6.1.2.1.2.2.1.1.1 = 1; 1.3.6.1.2.1.2.2.1.2.1 = 4d:53:20:54:43:50:20:4c:6f:6f:70:62:61:63:6b:20:69:6e:74:65:72:66:61:63:65:00]] 

We obtained the uptime value, the index of the first interface and its name, encoded by a string of octets in hexadecimal representation. To get the following lines, we must perform successive requests, passing the previously received OIDs.

Given the need to support the possibility of asynchronous processing, this can become a non-trivial (but completely solvable) task. Fortunately, in the 2nd version of SNMP, bulk queries were added to automate the retrieval of tabular data and minimize the number of queries sent while doing so. Make the necessary changes to the code:

BULK request
 package com.acme.ae.tests.snmp; import java.io.IOException; import java.util.HashSet; import java.util.Set; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class Test implements ResponseListener { private final static String SNMP_COMMUNITY = "public"; private final static int SNMP_RETRIES = 3; private final static long SNMP_TIMEOUT = 1000L; private final static int BULK_SIZE = 50; private Snmp snmp = null; private TransportMapping transport = null; private Set<Integer32> requests = new HashSet<Integer32>(); public void onResponse(ResponseEvent event) { Integer32 requestId = event.getRequest().getRequestID(); PDU response = event.getResponse(); if (response != null) { System.out.println(response.toString()); return; } else { synchronized (requests) { if (requests.contains(requestId)) { System.out.println("Timeout exceeded"); } } } synchronized (requests) { requests.remove(requestId); } } private void test() throws IOException { Target t = getTarget("udp:127.0.0.1/161"); send(t, new String[] {"1.3.6.1.2.1.1.3", "1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2"}); } private void send(Target target, String[] oids) throws IOException { PDU pdu = new PDU(); for (String oid: oids) { pdu.add(new VariableBinding(new OID(oid))); } pdu.setType(PDU.GETBULK); pdu.setMaxRepetitions(BULK_SIZE); pdu.setNonRepeaters(1); ResponseEvent event = snmp.send(pdu, target, null); synchronized (requests) { requests.add(pdu.getRequestID()); } onResponse(event); } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version2c); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String[] args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } } 


Having executed this query, we get all the rows of the table in one query:

A lot of data
 RESPONSE[requestID=1801703572, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.1.3.0 = 4:58:44.56; 1.3.6.1.2.1.2.2.1.1.1 = 1; 1.3.6.1.2.1.2.2.1.2.1 = 4d:53:20:54:43:50:20:4c:6f:6f:70:62:61:63:6b:20:69:6e:74:65:72:66:61:63:65:00; 1.3.6.1.2.1.2.2.1.1.2 = 2; 1.3.6.1.2.1.2.2.1.2.2 = 56:4d:77:61:72:65:20:56:69:72:74:75:61:6c:20:45:74:68:65:72:6e:65:74:20:41:64:61:70:74:65:72:20:66:6f:72:20:56:4d:6e:65:74:38:00; 1.3.6.1.2.1.2.2.1.1.3 = 3; 1.3.6.1.2.1.2.2.1.2.3 = 56:4d:77:61:72:65:20:56:69:72:74:75:61:6c:20:45:74:68:65:72:6e:65:74:20:41:64:61:70:74:65:72:20:66:6f:72:20:56:4d:6e:65:74:31:00; 1.3.6.1.2.1.2.2.1.1.65541 = 65541; 1.3.6.1.2.1.2.2.1.2.65541 = 52:65:61:6c:74:65:6b:20:52:54:4c:38:31:36:38:2f:38:31:31:31:20:50:43:49:2d:45:20:47:69:67:61:62:69:74:20:45:74:68:65:72:6e:65:74:20:4e:49:43:20:2d:20:44:65:74:65:72:6d:69:6e:69:73:74:69:63:20:4e:65:74:77:6f:72:6b:20:45:6e:68:61:6e:63:65:72:20:4d:69:6e:69:70:6f:72:74:00; 1.3.6.1.2.1.2.2.1.1.65542 = 65542; 1.3.6.1.2.1.2.2.1.2.65542 = 4e:6f:72:74:65:6c:20:49:50:53:45:43:53:48:4d:20:41:64:61:70:74:65:72:20:2d:20:44:65:74:65:72:6d:69:6e:69:73:74:69:63:20:4e:65:74:77:6f:72:6b:20:45:6e:68:61:6e:63:65:72:20:4d:69:6e:69:70:6f:72:74:00; 1.3.6.1.2.1.2.2.1.1.65543 = 65543; 1.3.6.1.2.1.2.2.1.2.65543 = 4e:6f:72:74:65:6c:20:56:50:4e:20:41:64:61:70:74:65:72:20:2d:20:44:65:74:65:72:6d:69:6e:69:73:74:69:63:20:4e:65:74:77:6f:72:6b:20:45:6e:68:61:6e:63:65:72:20:4d:69:6e:69:70:6f:72:74:00; 1.3.6.1.2.1.2.2.1.2.1 = 4d:53:20:54:43:50:20:4c:6f:6f:70:62:61:63:6b:20:69:6e:74:65:72:66:61:63:65:00; 1.3.6.1.2.1.2.2.1.3.1 = 24; 1.3.6.1.2.1.2.2.1.2.2 = 56:4d:77:61:72:65:20:56:69:72:74:75:61:6c:20:45:74:68:65:72:6e:65:74:20:41:64:61:70:74:65:72:20:66:6f:72:20:56:4d:6e:65:74:38:00; 1.3.6.1.2.1.2.2.1.3.2 = 6; 1.3.6.1.2.1.2.2.1.2.3 = 56:4d:77:61:72:65:20:56:69:72:74:75:61:6c:20:45:74:68:65:72:6e:65:74:20:41:64:61:70:74:65:72:20:66:6f:72:20:56:4d:6e:65:74:31:00; 1.3.6.1.2.1.2.2.1.3.3 = 6; 1.3.6.1.2.1.2.2.1.2.65541 = 52:65:61:6c:74:65:6b:20:52:54:4c:38:31:36:38:2f:38:31:31:31:20:50:43:49:2d:45:20:47:69:67:61:62:69:74:20:45:74:68:65:72:6e:65:74:20:4e:49:43:20:2d:20:44:65:74:65:72:6d:69:6e:69:73:74:69:63:20:4e:65:74:77:6f:72:6b:20:45:6e:68:61:6e:63:65:72:20:4d:69:6e:69:70:6f:72:74:00; 1.3.6.1.2.1.2.2.1.3.65541 = 6; 1.3.6.1.2.1.2.2.1.2.65542 = 4e:6f:72:74:65:6c:20:49:50:53:45:43:53:48:4d:20:41:64:61:70:74:65:72:20:2d:20:44:65:74:65:72:6d:69:6e:69:73:74:69:63:20:4e:65:74:77:6f:72:6b:20:45:6e:68:61:6e:63:65:72:20:4d:69:6e:69:70:6f:72:74:00; 1.3.6.1.2.1.2.2.1.3.65542 = 6; 1.3.6.1.2.1.2.2.1.2.65543 = 4e:6f:72:74:65:6c:20:56:50:4e:20:41:64:61:70:74:65:72:20:2d:20:44:65:74:65:72:6d:69:6e:69:73:74:69:63:20:4e:65:74:77:6f:72:6b:20:45:6e:68:61:6e:63:65:72:20:4d:69:6e:69:70:6f:72:74:00; 1.3.6.1.2.1.2.2.1.3.65543 = 6; 1.3.6.1.2.1.2.2.1.3.1 = 24; 1.3.6.1.2.1.2.2.1.4.1 = 1520; 1.3.6.1.2.1.2.2.1.3.2 = 6; 1.3.6.1.2.1.2.2.1.4.2 = 1500; 1.3.6.1.2.1.2.2.1.3.3 = 6; 1.3.6.1.2.1.2.2.1.4.3 = 1500; 1.3.6.1.2.1.2.2.1.3.65541 = 6; 1.3.6.1.2.1.2.2.1.4.65541 = 1500; 1.3.6.1.2.1.2.2.1.3.65542 = 6; 1.3.6.1.2.1.2.2.1.4.65542 = 1402; 1.3.6.1.2.1.2.2.1.3.65543 = 6; 1.3.6.1.2.1.2.2.1.4.65543 = 1376; 1.3.6.1.2.1.2.2.1.4.1 = 1520; 1.3.6.1.2.1.2.2.1.5.1 = 10000000; 1.3.6.1.2.1.2.2.1.4.2 = 1500; 1.3.6.1.2.1.2.2.1.5.2 = 100000000; 1.3.6.1.2.1.2.2.1.4.3 = 1500; 1.3.6.1.2.1.2.2.1.5.3 = 100000000; 1.3.6.1.2.1.2.2.1.4.65541 = 1500; 1.3.6.1.2.1.2.2.1.5.65541 = 100000000; 1.3.6.1.2.1.2.2.1.4.65542 = 1402; 1.3.6.1.2.1.2.2.1.5.65542 = 10000000; 1.3.6.1.2.1.2.2.1.4.65543 = 1376; 1.3.6.1.2.1.2.2.1.5.65543 = 10000000; 1.3.6.1.2.1.2.2.1.5.1 = 10000000; 1.3.6.1.2.1.2.2.1.6.1 = ; 1.3.6.1.2.1.2.2.1.5.2 = 100000000; 1.3.6.1.2.1.2.2.1.6.2 = 00:50:56:c0:00:08; 1.3.6.1.2.1.2.2.1.5.3 = 100000000; 1.3.6.1.2.1.2.2.1.6.3 = 00:50:56:c0:00:01; 1.3.6.1.2.1.2.2.1.5.65541 = 100000000; 1.3.6.1.2.1.2.2.1.6.65541 = 00:18:f3:08:06:13; 1.3.6.1.2.1.2.2.1.5.65542 = 10000000; 1.3.6.1.2.1.2.2.1.6.65542 = 44:45:53:54:42:00; 1.3.6.1.2.1.2.2.1.5.65543 = 10000000; 1.3.6.1.2.1.2.2.1.6.65543 = 00:ff:97:65:06:be; 1.3.6.1.2.1.2.2.1.6.1 = ; 1.3.6.1.2.1.2.2.1.7.1 = 1; 1.3.6.1.2.1.2.2.1.6.2 = 00:50:56:c0:00:08; 1.3.6.1.2.1.2.2.1.7.2 = 1; 1.3.6.1.2.1.2.2.1.6.3 = 00:50:56:c0:00:01; 1.3.6.1.2.1.2.2.1.7.3 = 1; 1.3.6.1.2.1.2.2.1.6.65541 = 00:18:f3:08:06:13; 1.3.6.1.2.1.2.2.1.7.65541 = 1; 1.3.6.1.2.1.2.2.1.6.65542 = 44:45:53:54:42:00; 1.3.6.1.2.1.2.2.1.7.65542 = 1; 1.3.6.1.2.1.2.2.1.6.65543 = 00:ff:97:65:06:be; 1.3.6.1.2.1.2.2.1.7.65543 = 1; 1.3.6.1.2.1.2.2.1.7.1 = 1; 1.3.6.1.2.1.2.2.1.8.1 = 1; 1.3.6.1.2.1.2.2.1.7.2 = 1; 1.3.6.1.2.1.2.2.1.8.2 = 1; 1.3.6.1.2.1.2.2.1.7.3 = 1; 1.3.6.1.2.1.2.2.1.8.3 = 1; 1.3.6.1.2.1.2.2.1.7.65541 = 1; 1.3.6.1.2.1.2.2.1.8.65541 = 1; 1.3.6.1.2.1.2.2.1.7.65542 = 1; 1.3.6.1.2.1.2.2.1.8.65542 = 1; 1.3.6.1.2.1.2.2.1.7.65543 = 1; 1.3.6.1.2.1.2.2.1.8.65543 = 2; 1.3.6.1.2.1.2.2.1.8.1 = 1; 1.3.6.1.2.1.2.2.1.9.1 = 0:00:00.00; 1.3.6.1.2.1.2.2.1.8.2 = 1; 1.3.6.1.2.1.2.2.1.9.2 = 0:00:00.00; 1.3.6.1.2.1.2.2.1.8.3 = 1; 1.3.6.1.2.1.2.2.1.9.3 = 0:00:00.00; 1.3.6.1.2.1.2.2.1.8.65541 = 1; 1.3.6.1.2.1.2.2.1.9.65541 = 0:00:00.00; 1.3.6.1.2.1.2.2.1.8.65542 = 1; 1.3.6.1.2.1.2.2.1.9.65542 = 0:00:00.00; 1.3.6.1.2.1.2.2.1.8.65543 = 2; 1.3.6.1.2.1.2.2.1.9.65543 = 0:00:00.00; 1.3.6.1.2.1.2.2.1.9.1 = 0:00:00.00; 1.3.6.1.2.1.2.2.1.10.1 = 3542209; 1.3.6.1.2.1.2.2.1.9.2 = 0:00:00.00; 1.3.6.1.2.1.2.2.1.10.2 = 40700]] 


Of course, if the table contains more than the requested 50 rows, again (as for the 1st version of SNMP) you will need to form queries to receive subsequent rows, passing in them the OID received for the last row.

What I did not tell?


In this article, I did not talk about much. I did not talk about how to change the values ​​of some (not all) variables with SET requests. I did not talk about what TRAPs are and why they are needed. I have not said a word about how to develop SNMP agents. And I did not say a single word about the 3rd version of SNMP and the changes introduced to it.

But even what I said is enough to understand that SNMP is not easy.

With a serious approach to the issue.

Source: https://habr.com/ru/post/196308/


All Articles