SNMP Protocol Messages - GetNext and GetBulk

The Need for GetNext Requests

Do you remember when we looked at tables that we saw that with some tables we don't we don't know how many rows there are and the index is not integral? A GetRequest would not be very helpful to find the entries in the IP address table - each IP address is, in fact, the index for its row in the table! How can I ask for them if I don't know them? They are not indexed by an integer so that I could say "give me the first one, give me the second one, etc." So, how am I to ask for this information?

The answer is that I use what is called a traversal operation, which allows me to traverse from node to node in a tree, in lexicographic order of the OIDs. Traversing a Management Information Tree would look like Figure 53.

Figure 53: Traversing a Tree

We could start from any node in the tree, by naming its OID, and sending a GetNext request. When we get the response to that, we know the next OID and we can send a GetNext request for that OID, etc. This is sometimes called a "MIB Walk". (You have a button like that in the BlackOwl MIB Browswer, when you are looking at the Tree view). Though a "MIB Walk" really means that you keep doing this until you get to the end of the MIB, which you can tell because the response will have an error code, the expression is often used for traversing a portion of a MIB - a table or a group.

Using GetNext

So, if we want the ipAddrTable (that's the old MIB-2 version of the IP address table), what OID do you think we would start with? Actually, you could start with at least two other OIDs, and any one of them would work. Can you name two other two possibilities? If you would do a MIB walk starting at any one of those OIDs, do you think the table would fill in row-by-row or column-by-column? Can you explain why? In the previous chapter, you saw how to set up the SNMP agent in a Windows computer. Assuming your SNMP agent is still enabled, you can try a MIB walk beginning with ipAddrTable (the first OID answer that I gave) and see the results, as shown in Figure 54.

Figure 54: MIB Walk for ipAddrTable Values

Notice that I first received all three instances for the first column, then for the second column, then for the third, etc. (according to the definition of ipAddrEntry). You can also try it beginning with ipAddrEntry and see that the results will be the same. But if you begin with ipAdEntAddr, the software will not continue the GetNext beyond the first column (it thinks you only want the instances for one object in the table), even though if you were to keep doing GetNext on the last OID, you would traverse to the next column, and on. How, then, if you just keep doing GetNext, do you know when you reached the end of the table? We know we have moved on to the next MIB object when the OID begins with 1.3.6.1.2.1.4.21.

Now that you see how this works, can you think of a more efficient way to fill in a table, still using the GetNext operation? This time, I won't make you read the answer with a "mouse-over" - it is a bit too long to read that way! Since we can send a request for multiple variables (remember the variable bindings list?) in one request, and since we know the OID of each row entry - in effect, the column headers, we can send a GetNext for 1.3.6.1.2.1.4.20.1.1, 1.3.6.1.2.1.4.20.1.2, 1.3.6.1.2.1.4.20.1.3, 1.3.6.1.2.1.4.20.1.4, and 1.3.6.1.2.1.4.20.1.5. (Those are the OIDs for ipAdEntAddr, ipAdEntIfIndex, ipAdEntNetMask, etc.) We will get the first row in the table in response, with the OIDs of those variables. We can then use those OIDs to get the second row, etc. So, we can get the table row-by-row if we request multiple variables in each request!

But think for a moment what happens when we do a GetNext on the last row (of course, not knowing that it is the last row) - the response for the last instance in the first column will be the top of the second column (which we already have!), so we would know that we've reached the end of the first column. Similarly, for the second column, etc., until the last column. The response for the last instance in the last column would be the next MIB object that is not in the table.

Hands-on GetNext

As in the previous chapter, the best option for a hands-on experience is for you to send GetNext queries to an SNMP agent and capture the packets. Refer to the previous chapter to see how to do that, using your MIB browser software and the packet capture software, except use the "get next" button, instead. However, for those who are not able to capture their own files, you can download my capture file and open it with Wireshark. Again, even if you do not capture your own packets, I encourage you to take the time to examine my capture file yourself. Pay attention to the OID in the variable bindings of both a query and corresponding response - you'll see that if a GetNext is sent for 1.3.6.1.2.1.2.2.1.4.23 (ifMtu.23) (Figure 55), then the response contains the value (1500) of the next instance, 1.3.6.1.2.1.2.2.1.4.24 (Figure 56).

Figure 55: GetNext Request ifMtu.23



Figure 56: Response ifMtu.24

Interactive Activities

You are now welcome to return to the interactive applet that you saw in the previous chapter and try it with construction of a GetNext request. You also might have taken a look at the other interactive activity that I had recommended - the Simpleweb interactive tutorial, but for GetNext I must warn you that the processing of the table is overly simplified in that the first two columns are skipped - they are used only as indices, but are not returned as values, as would be the case with a real application. (And if you keep doing GetNext, you will see OIDs appear that aren't displayed in the diagram.)

The Purpose of GetBulk

The GetBulk Request, introduced in SNMPv2, is an enhancement of the GetNext Request, intended to efficiently retrieve bulk data. In particular, it is most beneficial for retrieving multiple rows from a table. I explained above that we can retrieve a row of a table using a GetNext Request, by requesting multiple variable values in the variable bindings list. But we can still only request one row at a time, because we don't know the index value of the next row. The GetBulk Request permits us to request multiple rows. Using GetBulk is like saying "do GetNext a bunch of times."

Figure 57 shows the format of the GetBulk message, which differs slightly from all the other SNMPv2 messages, the format for which you saw in the previous chapter. The Error Status and Error Index fields were replaced with two different fields. In any event, in any other request message (Get or GetNext), the values of these fields is zero, as these fields are only used in response messages.

Figure 57: GetBulk Message Format

With a single GetBulk message, we can retrieve a number of non-repetitive scalar values and a number of repetitive tabular values. The non-repeaters field indicates the number of scalar values requested and the max repetitions field indicates the maximum number of table rows requested. The latter field gives a maximum value, because, as we saw, we don't always know how many rows a table has! (There are also limitations due to maximum message size.) Unlike a Get or GetNext request, there is not a one-to-one mapping between the variable bindings sent in the request and the varialble bindings in the response. We might get a much longer list in the response - in fact, that is the whole purpose of using a GetBulk message.

Hands-on GetBulk

The thing that is a bit odd about the GetBulk message is how it operates on the scalars - the non-repetitive objects. If I want to retrieve, say, five scalars, I set the value of the non-repeaters field to 5 and then in my variable bindings list I list the five OIDs preceding the OIDs that I want, because the operation that is performed is just like a GetNext. (To me it would have made more sense to perform a Get for the non-repeaters, but who am I?) If we play by the rules with OIDs, this is not a problem. Suppose I want to get the values of the System group. In the variable bindings list in my request I would have sysDescr, sysObjectID, sysUpTime, sysContact, etc. without appending the .0 at the end for the instance and the response would send me the variables sysDescr.0, sysObjectID.0, etc. and their values. In actuality, the OIDs I send would be 1.3.6.1.2.1.1.1, 1.3.6.1.2.1.1.2, etc. and I receive OIDs 1.3.6.1.2.1.1.1.0, 1.3.6.1.2.1.1.2.0, etc.

However, the BlackOwl MIB Browser software does not quite play by the rules. It appends the .0 to the object name, so that if you open your tree view and select, say, sysDescr, you'll see that the OID already has the .0 appended (I "spoke" about this before), as in Figure 58.

Figure 58: Example of Scalar OID Problem

If I want to use a GetBulk, I have no way to select a scalar without the .0 appended. So, to request a bunch of scalar values I have to be sure to list the preceding OIDs. With tabular objects, it works as expected - I select the object name for a column and no instance is specified in the OID. Let's look at an example. With the MIB Browser open and displaying the Tree view, I need to select one object in the MIB tree to enable use of the GetBulk button. My goal is to get the values of a bunch of scalars in the System group and then to get some columns in the Interface Table. Once I click on the GetBulk button, I can add other objects to the list, if I with, I can reorder them using the arrows on the right, or delete them with the - button. I can specify the number of non-repeaters and the value of max repetitions. Figure 59 shows my GetBulk window set up to go.

Figure 59: Example of GetBulk Parameters

Remember, the actual list of scalars for which I wish to get values are sysDescr, sysObjectID, sysUpTime, sysContact, sysName, sysLocation, sysServices (7 non-repeaters). Each name specified in the window shown in Figure 59 will bring me the value of the next object in the MIB tree. I then have 4 tabular objects for which I want a maximum of 6 repetitions (4 columns by 6 rows). The results of this GetBulk operation are shown in Figure 60.

Figure 60: Example of GetBulk Results

I queried a device on the network, but you can do this with your own computer using localhost as the host. (You saw how to do that earlier.) Notice that the scalar values returned are for the 7 scalars that I really wanted (GetNext for each of those sent).

Lastly, if you are able to query an agent other than your own computer, you can capture packets and examine them. Otherwise, as before, you can examine my capture file. Figures 61 and 62 show the request and the response, respectively. As before, pay attention (and this is better if you do it with Wireshark, as you can't see everything in the image shown here) to all the fields we talked about: the non-repeaters, max repetitions, etc. Notice the OIDs and how the OIDs returned are each lexicographically the one following the OIDs that were sent. Notice that the total number of variable bindings sent is 11 while the total number received is 31 (7+4x6). Cool!

Figure 61: Capture of GetBulk Request

Figure 62: Capture of GetBulk Response

The interactive applet that you saw previously does not support the SNMPv2 GetBulk operation, but you might want to see how the other interactive activity that I had recommended - the Simpleweb interactive tutorial handles GetBulk. Like with GetNext, it does not exactly simulate a real application, but is is fun and educational, nevertheless.

The last chapter on SNMP messages is about traps.

Previous Next

www.rad.com