Why is SNMP not so simple?

  • Tutorial
A long time ago, an article was published on Habr that talks about how to use the popular library for working with SNMP from a Java application. Supporting, in general, the author’s undertaking, I want to dwell on the difficulties that may arise in a real project that uses SNMP.

Read the documentation


To begin with, I would like to dwell on the fact that it is not entirely clear to me why, from the whole variety of SNMP requests, the author settled on TRAPs? Let's see what RFC 1157 writes about this :
The strategy implicit in the SNMP is that the monitoring of network state at any significant level of detail is accomplished primarily by polling for appropriate information on the part of the monitoring center (s). A limited number of unsolicited messages (traps) guide the timing and focus of the polling. Limiting the number of unsolicited messages is consistent with the goal of simplicity and
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 monitoring the status of a network with any significant level of detail is done mainly by polling from a monitoring center. A limited number of unsolicited messages (trap - interrupt) provides synchronization and activates polls. Limiting the number of unsolicited messages is consistent with the tasks of ensuring simplicity and minimizing the traffic created by the network management system.

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

In general, I highly recommend that you familiarize yourself with all of the SNMP-related RFCs before you get started. Some aspects of SNMP are not obvious and it makes sense to get an idea of ​​them from the original source. You can start familiarizing yourself with the material on the wiki .

First steps


In addition to the mandatory familiarization with the documentation, it is important to understand why we all do this. In telecom practice, the following tasks are most often encountered:

  1. Survey of equipment via SNMP (accounting, monitoring)
  2. SNMP equipment management (activation)

The tasks associated with the survey of equipment are reduced to the formation of GET (and, as GETNEXT will show later) 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 disable some interface).

The task of SNMP monitoring stands out against the general background by the requirement that the equipment being surveyed is many or very many. Suppose that it is precisely this problem that we have to solve.

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

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());
		}
	}
}


After making sure that the SNMP service on our host is working and running the code for execution, we get the desired uptime value (the time the host has stopped working 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 from the moment of the next poll. If the host did not respond within the specified timeout (after several automatic 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 queries we can execute per second? Let's make a small correction in 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 to execute:

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 somewhat faster than the local network. Let's see how many requests per second we have time to complete to another host on our network:

182

Do not even reach two hundred. Generally speaking, perhaps this will be enough. It all depends on the task. But we took measurements provided that the host being interviewed 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 complete a single request. Since a non-responding host is not so rare, this can be a big problem in a real project.

Go to the record


What can be done with this? If we were dealing with any synchronous protocol (for example telnet), we would not have much choice. In order to increase productivity, we would have to execute many threads simultaneously. But SNMP is asynchronous in nature! No need to force it into the synchronous frames.

How to go to the asynchronous option? In our case, it’s pretty 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 did not respond?

Very simple, after a specified number of attempts and timeouts, SNMP4J will return an event, response in which 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 requests = new HashSet();
	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());
		}
	}
}


We 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 answer most of the requests (accordingly, the messages “Timeout exceeded” remain in the log). Of course, this will not be a problem when we start polling a large number of devices with a reasonable interval between requests.

We go further


We learned how to obtain the values ​​of scalar variables from SNMP. But, besides them, there are also tables in SNMP (for example, the interface table on the device). How are they arranged? Let's look at the MIB-browser:

image

In OID mgmt.interfaces (1.3.6.1.2.1.2) we see the scalar variable ifNumber (1.3.6.1.2.1.2.1) containing 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 numerical index ifIndex of an interface has OID = 1.3.6.1.2.1.2.2.1.1.

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

image

For this purpose, the GETNEXT request was invented. Passing the OID prefix to this request, we get the OID and the value of the next (in lexicographic order) after this prefix variable. This means that passing the prefixes of the OIDs of the table columns, we get the OIDs and the values ​​of its first row. To get the next line, you need to perform another request, passing in it the OIDs received by the previous request. And so on until we look through the entire table.

Of course, taking into account all of the above, we should minimize the number of queries (this is also necessary given the fact that within one query, according to the RFC, consistent data is provided, if we query the index and interface name with two consecutive queries, they may not correspond each other). As part of the 1st version of SNMP, we must read the entire row of the table with one query.

It should be noted that it is quite convenient that the OIDs of scalar variables are also prefixes. For example, for the sysUpTime OID variable, it is actually 1.3.6.1.2.1.1.3. We can pass it to the GETNEXT request and get OID = 1.3.6.1.2.1.1.3.0 along with the corresponding value. This makes it possible to query scalar values ​​together with table column values ​​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 requests = new HashSet();
	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 got the uptime value, the index of the first interface and its name encoded by the octet string in hexadecimal representation. To get the following lines, we must execute sequential 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 requests were added, automating the receipt of tabular data and minimizing the number of requests sent. 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 requests = new HashSet();
	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 with 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 lines, again (as for the 1st version of SNMP) it will be necessary to form queries to receive the next lines, passing in them the OID received for the last line.

What didn’t I talk about?


In this article I did not talk about a lot. I did not talk about how to change the values ​​of some (not all) variables with SET queries. I did not talk about what TRAPs are and why they are needed. I did not say a word about how to develop SNMP agents. And I did not mention 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.

Also popular now: