How does an SNMP manager walk a MIB table with GetNextRequest, and how does it know the table has ended?
answer
- ask for what comes after
- OIDs compare number by number
- column by column, row by row
- feed the returned name back
- prefix changes, walk is over
basics
~20 sThe manager sends GetNextRequest with a column's OID, gets the first instance after it, and keeps sending back the name it received. The column has ended when a returned name leaves the column's OID prefix, or the agent returns endOfMibView.
solid answer
~40 sA `GetNextRequest` returns, for each name, the first instance that follows it in lexicographic OID order, together with that instance's name. Instance names are the column OID plus the row index, and OIDs compare sub-identifier by sub-identifier as numbers, so a table is ordered column by column and, within a column, by index. The manager starts with the bare column OID, receives the first row's instance, and sends that name back to get the next one. Putting several columns in one request returns one whole row per exchange. The walk ends when a returned name falls outside the column's prefix, because the agent has moved on to the next column or past the table, or when an SNMPv2 agent returns `endOfMibView` because nothing follows in the view.
go deeper
Remember that GetNext returns the next instance's name and value, and that a walk keeps feeding the returned name back until the prefix changes.
Explain lexicographic OID order, why tables come back column by column, and the three ways a walk can end: a prefix change, endOfMibView, or SNMPv1's noSuchName.
Point out that a walk is many reads at different moments, costs one round trip per row, and needs a guard against agents that return non-increasing names.
Weigh what walk-based collection costs across a large estate, and when a table's size makes per-row round trips the wrong collection model.
## Why a manager needs GetNext at all A **MIB table** is a set of *columnar objects*, one per column, such as `ifDescr` (`1.3.6.1.2.1.2.2.1.2`) and `ifType` (`1.3.6.1.2.1.2.2.1.3`) in the Interfaces MIB. One cell of the table is an **instance**, named by the column's OBJECT IDENTIFIER followed by the row's **index**: `ifDescr.2` is the description of the row with index 2. A `GetRequest` can read a cell only if the manager already knows its full name, and for most tables it does not. RFC 2863 says plainly that `ifIndex` values need not be contiguous, so the table can have holes, and that SNMP's GetNext (and GetBulk) operation deals with them easily. Other tables are indexed by IP addresses or by several columns at once, and those values cannot be guessed. **GetNext** solves this by returning the *name* of what it found as well as its value. ## Lexicographic order RFC 3416 defines the GetNext answer as the variable whose name is the **first lexicographic successor** of the name in the request, among all variables accessible to that request. For OBJECT IDENTIFIERs that means comparing **sub-identifier by sub-identifier, as numbers**, with a shorter name ordering before any longer name it is a prefix of: | Name | Why it sorts here | |---|---| | `ifDescr` | the column OID itself, a prefix of every instance | | `ifDescr.1` | first row | | `ifDescr.2` | 2 < 9 | | `ifDescr.9` | 9 < 10 as numbers (as text, "10" would sort first) | | `ifDescr.10` | last row in this column | | `ifType.1` | next column (`...1.3` follows `...1.2`) | Two consequences follow. A table is laid out **column by column**: every row of `ifDescr`, then every row of `ifType`. And the bare column OID is a perfect starting point, because the first instance in the column is its successor. ## The walk, step by step For a table whose rows have indexes 1, 2, 9 and 10: 1. `GetNextRequest(ifDescr)` returns `ifDescr.1`. 2. `GetNextRequest(ifDescr.1)` returns `ifDescr.2`. 3. `GetNextRequest(ifDescr.2)` returns `ifDescr.9`; the hole at 3 to 8 costs nothing. 4. `GetNextRequest(ifDescr.9)` returns `ifDescr.10`. 5. `GetNextRequest(ifDescr.10)` returns `ifType.1`. The name no longer begins with `ifDescr`, so the column is finished and the manager discards this binding. Four rows took five exchanges: one per row, plus one to discover the end. To read several columns of the same row at once, the manager puts one binding per column in a single request, as RFC 3416's own example does with two columns plus `sysUpTime`. Each reply then returns one row across those columns. ## How the walk ends - **The prefix changes.** In both SNMPv1 and SNMPv2, the normal end of a column is a returned name outside the column's OID. RFC 3416's example shows both forms: one binding *wraps* to the first row of the next column, another jumps to the first object after the whole table. - **`endOfMibView`.** If nothing at all follows the name in the request's MIB view, an SNMPv2 or SNMPv3 agent returns this exception in that binding, with the name set to the name the manager sent, and `error-status` stays `noError`. - **SNMPv1's `noSuchName`.** An SNMPv1 agent (RFC 1157, now Historic) reports the same situation as the error-status `noSuchName`, which fails the whole request. - **A defensive stop.** A careful manager also stops if a returned name is not greater than the one it sent, because an agent that returns a non-increasing name would otherwise keep the walk going for ever. ## What a walk is, and is not A walk is **many separate requests**, not a snapshot. Rows can appear or disappear between exchanges, so the result is a sequence of reads taken at slightly different times; RFC 3416's example includes `sysUpTime` in every request so that the manager knows when each reply was produced. A walk also sees only the **MIB view** the request is allowed to read: objects outside it are skipped as though they did not exist. And it is slow by construction. Each row costs a full round trip and a full trip through the agent's message processing, which is why large tables are read with `GetBulkRequest`, the same successor step repeated many times inside one exchange.
- Why would an SNMP manager put several column OIDs into one GetNextRequest?Each binding advances independently, so naming three columns returns the next instance of each: in a well-filled table, one complete row per exchange instead of one cell. The manager tracks each column's last name separately, because a column with missing cells can run ahead of the others or finish first.
- What does a GetNextRequest return when it names an instance that does not exist, such as ifDescr.5 on a table with rows 2 and 9?The first instance after that name: `ifDescr.9`. GetNext never needs the name it is given to exist; it only needs a successor. That is why a walk can start from the bare column OID, and why holes in the index cost nothing.
Like reading a shelf of books you cannot see by asking a librarian, again and again, "which book comes right after this one?" You never need the titles in advance, each answer is the starting point for the next question, and you know the shelf is finished when the answer comes from a different shelf.
saying these in an interview costs you the question
- OIDs sort as text, so ifDescr.10 comes before ifDescr.9.
- Walking from a table's OID returns the table row by row.
- You must know the row indexes before you can read a table.
- GetNext on a missing instance returns noSuchInstance.
- A completed walk is a consistent snapshot of the table at one moment.