Search documentation of snmpkit

# SnmpKit.SnmpLib.Walker (snmpkit v1.2.0)

Efficient SNMP table walking with bulk operations and streaming support.

This module provides high-performance table walking capabilities using GETBULK operations for maximum efficiency. It's designed for collecting large amounts of SNMP data with minimal network overhead and memory usage.

## Features

- GETBULK Optimization: Uses GETBULK requests for 3-5x faster table walking
- Streaming Support: Process large tables without loading all data into memory
- Automatic Pagination: Handles table boundaries and end-of-mib-view conditions
- Error Recovery: Graceful handling of partial responses and network issues
- Adaptive Bulk Size: Automatically adjusts bulk size based on device capabilities
- Memory Efficient: Lazy evaluation and streaming for large datasets

## Table Walking Strategies

### Bulk Walking (Recommended)

Uses GETBULK operations for maximum efficiency. Best for SNMPv2c devices.

### Sequential Walking

Falls back to GETNEXT operations for SNMPv1 devices or when GETBULK fails.

### Streaming Walking

Processes table rows as they arrive, ideal for very large tables.

## Examples

    # Walk entire interface table
    {:ok, interfaces} = SnmpKit.SnmpLib.Walker.walk_table("192.168.1.1", [1, 3, 6, 1, 2, 1, 2, 2])

    # Stream large table to avoid memory issues
    SnmpKit.SnmpLib.Walker.stream_table("192.168.1.1", [1, 3, 6, 1, 2, 1, 2, 2, 1, 2])
    |> Stream.each(fn {interface_oid, interface_value} ->
         IO.puts("Interface: " <> inspect(interface_oid) <> " = " <> inspect(interface_value))
       end)
    |> Stream.run()

    # Walk with custom bulk size and timeout
    {:ok, data} = SnmpKit.SnmpLib.Walker.walk_table("10.0.0.1", "1.3.6.1.2.1.4.21",
                                            max_repetitions: 50, timeout: 15_000)

# Summary

## Types

host()
oid()
stream_chunk()
varbind()
walk_opts()
walk_result()

## Functions

estimate_table_size(host, table_oid, opts \\ [])

Estimates the size of a table by walking just the first column.

stream_table(host, table_oid, opts \\ [])

Streams table entries as they are retrieved, ideal for very large tables.

walk_column(host, column_oid, opts \\ [])

Walks a single table column efficiently.

walk_subtree(host, base_oid, opts \\ [])

Walks a subtree starting from the given OID.

walk_table(host, table_oid, opts \\ [])

Walks an entire SNMP table efficiently using GETBULK operations.

# Types

# host()

    @type host() :: binary() | :inet.ip_address()

# oid()

    @type oid() :: [non_neg_integer()] | binary()

# stream_chunk()

    @type stream_chunk() :: [varbind()]

# varbind()

    @type varbind() :: {oid(), any()}

# walk_opts()

    @type walk_opts() :: [
      community: binary(),
      version: :v1 | :v2c,
      timeout: pos_integer(),
      max_repetitions: pos_integer(),
      max_retries: non_neg_integer(),
      retry_delay: pos_integer(),
      port: pos_integer(),
      adaptive_bulk: boolean(),
      chunk_size: pos_integer()
    ]

# walk_result()

    @type walk_result() :: {:ok, [varbind()]} | {:error, any()}

# Functions

# estimate_table_size(host, table_oid, opts \\ [])

    @spec estimate_table_size(host(), oid(), walk_opts()) ::
      {:ok, non_neg_integer()} | {:error, any()}

Estimates the size of a table by walking just the first column.

Useful for determining table size before performing full table walks, helping with memory planning and progress estimation.

## Parameters

- `host`: Target device IP address or hostname
- `table_oid`: Base OID of the table
- `opts`: Walking options (typically with small max_repetitions)

## Returns

- `{:ok, count}`: Estimated number of table rows
- `{:error, reason}`: Estimation failed

## Examples

    # Test that estimate_table_size function exists and handles invalid input properly
    iex> match?({:error, _}, SnmpKit.SnmpLib.Walker.estimate_table_size("invalid.host", [1, 3, 6, 1, 2, 1, 2, 2], timeout: 100))
    true

# stream_table(host, table_oid, opts \\ [])

    @spec stream_table(host(), oid(), walk_opts()) :: Enumerable.t()

Streams table entries as they are retrieved, ideal for very large tables.

Returns a Stream that yields chunks of varbinds as they are collected. This is memory-efficient for large tables as it doesn't load all data at once.

## Parameters

- `host`: Target device IP address or hostname
- `table_oid`: Base OID of the table to stream
- `opts`: Streaming options (chunk_size controls entries per chunk)

## Returns

A Stream that yields `stream_chunk()` (lists of varbinds)

## Examples

    # Process large routing table in chunks
    # SnmpKit.SnmpLib.Walker.stream_table("192.168.1.1", [1, 3, 6, 1, 2, 1, 4, 21])
    # |> Stream.flat_map(& &1)  # Flatten chunks into individual varbinds
    # |> Stream.filter(fn {_oid, value} -> value != 0 end)  # Filter active routes
    # |> Enum.take(100)  # Take first 100 active routes
    # returns list of active routes

    # Test that stream_table function exists and returns a stream
    iex> stream = SnmpKit.SnmpLib.Walker.stream_table("invalid.host", "1.3.6.1.2.1.2.2.1.1", timeout: 100)
    iex> is_function(stream, 2)
    true

# walk_column(host, column_oid, opts \\ [])

    @spec walk_column(host(), oid(), walk_opts()) :: walk_result()

Walks a single table column efficiently.

Optimized for retrieving a single column from an SNMP table by using the column OID directly and stopping at table boundaries.

## Parameters

- `host`: Target device IP address or hostname
- `column_oid`: OID of the table column (e.g., [1,3,6,1,2,1,2,2,1,2] for ifDescr)
- `opts`: Walking options

## Returns

- `{:ok, column_data}`: List of {index_oid, value} pairs for the column
- `{:error, reason}`: Walking failed

## Examples

    # Test that walk_column function exists and handles invalid input properly
    iex> match?({:error, _}, SnmpKit.SnmpLib.Walker.walk_column("invalid.host", [1, 3, 6, 1, 2, 1, 2, 2, 1, 2], timeout: 100))
    true

# walk_subtree(host, base_oid, opts \\ [])

    @spec walk_subtree(host(), oid(), walk_opts()) :: walk_result()

Walks a subtree starting from the given OID.

Similar to walk_table/3 but continues until the OID prefix no longer matches, making it suitable for walking MIB subtrees that may contain multiple tables.

## Parameters

- `host`: Target device IP address or hostname
- `base_oid`: Starting OID for the subtree walk
- `opts`: Walking options

## Returns

- `{:ok, varbinds}`: All OIDs under the base_oid with their values
- `{:error, reason}`: Walking failed

## Examples

    # Test that walk_subtree function exists and handles invalid input properly
    iex> match?({:error, _}, SnmpKit.SnmpLib.Walker.walk_subtree("192.168.255.254", [1, 3, 6, 1, 2, 1, 1], timeout: 100))
    true

# walk_table(host, table_oid, opts \\ [])

    @spec walk_table(host(), oid(), walk_opts()) :: walk_result()

Walks an entire SNMP table efficiently using GETBULK operations.

This is the most efficient way to retrieve a complete SNMP table. Uses GETBULK requests when possible (SNMPv2c) and automatically handles table boundaries.

## Parameters

- `host`: Target device IP address or hostname
- `table_oid`: Base OID of the table to walk
- `opts`: Walking options (see module docs)

## Returns

- `{:ok, varbinds}`: List of {oid, value} pairs for all table entries
- `{:error, reason}`: Walking failed with reason

## Examples

    # Test that walk_table function exists and handles invalid input properly
    iex> match?({:error, _}, SnmpKit.SnmpLib.Walker.walk_table("192.168.255.254", [1, 3, 6, 1, 2, 1, 2, 2], timeout: 50))
    true

    # Walk with high bulk size for faster collection
    # SnmpKit.SnmpLib.Walker.walk_table("10.0.0.1", "1.3.6.1.2.1.2.2", max_repetitions: 50)
    # {:ok, [...]} returns many interface entries