SnmpKit ๐
A modern, comprehensive SNMP toolkit for Elixir - featuring a unified API, pure Elixir implementation, and powerful device simulation.
SnmpKit is a complete SNMP (Simple Network Management Protocol) solution built from the ground up in pure Elixir. It provides a clean, organized API for SNMP operations, MIB management, and realistic device simulation - perfect for network monitoring, testing, and development.
โจ Key Features
- ๐ฏ Unified API - Clean, context-based modules (
SnmpKit.SNMP
,SnmpKit.MIB
,SnmpKit.Sim
) - ๐งฌ Pure Elixir Implementation - No Erlang SNMP dependencies
- ๐ Advanced MIB Support - Native parsing, compilation, and object resolution
- ๐ฅ๏ธ Realistic Device Simulation - Create SNMP devices for testing and development
- โก High Performance - Optimized for large-scale operations and concurrent requests
- ๐งช Testing Friendly - Comprehensive test helpers and simulated devices
- ๐ง Modern Architecture - GenServer patterns, supervision trees, circuit breakers
- ๐ Enterprise Ready - DOCSIS, standard MIBs, and custom implementations
- ๐ Zero Warnings - Clean, production-ready codebase
๐ Quick Start
Installation
Add snmpkit
to your list of dependencies in mix.exs
:
def deps do
[
{:snmpkit, "~> 0.2.0"}
]
end
Unified API Examples
SnmpKit provides a clean, organized API through context-based modules:
๐ก SNMP Operations (SnmpKit.SNMP
)
# Basic SNMP operations
{:ok, description} = SnmpKit.SNMP.get("192.168.1.1", "sysDescr.0")
{:ok, uptime} = SnmpKit.SNMP.get("192.168.1.1", "sysUpTime.0")
# Walk operations
{:ok, system_info} = SnmpKit.SNMP.walk("192.168.1.1", "system")
{:ok, interface_table} = SnmpKit.SNMP.get_table("192.168.1.1", "ifTable")
# Bulk operations for efficiency
{:ok, results} = SnmpKit.SNMP.bulk_walk("192.168.1.1", "interfaces")
# Multi-target operations
{:ok, results} = SnmpKit.SNMP.get_multi([
{"host1", "sysDescr.0"},
{"host2", "sysUpTime.0"},
{"host3", "ifInOctets.1"}
])
# Pretty formatting
{:ok, formatted} = SnmpKit.SNMP.get_pretty("192.168.1.1", "sysUpTime.0")
# Returns: "12 days, 4:32:10.45"
# Async operations
task = SnmpKit.SNMP.get_async("192.168.1.1", "sysDescr.0")
{:ok, result} = Task.await(task)
๐ MIB Operations (SnmpKit.MIB
)
# OID name resolution
{:ok, oid} = SnmpKit.MIB.resolve("sysDescr.0")
# Returns: [1, 3, 6, 1, 2, 1, 1, 1, 0]
# Reverse lookup
{:ok, name} = SnmpKit.MIB.reverse_lookup([1, 3, 6, 1, 2, 1, 1, 1, 0])
# Returns: "sysDescr.0"
# MIB compilation and loading
{:ok, compiled} = SnmpKit.MIB.compile("MY-CUSTOM-MIB.mib")
{:ok, _} = SnmpKit.MIB.load(compiled)
# Tree navigation
{:ok, children} = SnmpKit.MIB.children([1, 3, 6, 1, 2, 1, 1])
{:ok, parent} = SnmpKit.MIB.parent([1, 3, 6, 1, 2, 1, 1, 1, 0])
๐งช Device Simulation (SnmpKit.Sim
)
# Load a device profile
{:ok, profile} = SnmpKit.SnmpSim.ProfileLoader.load_profile(
:cable_modem,
{:walk_file, "priv/walks/cable_modem.walk"}
)
# Start a simulated device
{:ok, device} = SnmpKit.Sim.start_device(profile, port: 1161)
# Create a population of devices for testing
device_configs = [
%{type: :cable_modem, port: 30001, community: "public"},
%{type: :switch, port: 30002, community: "public"},
%{type: :router, port: 30003, community: "private"}
]
{:ok, devices} = SnmpKit.Sim.start_device_population(device_configs)
๐ฏ Direct Access (Backward Compatibility)
For convenience, common operations are also available directly:
# These work the same as their SnmpKit.SNMP.* equivalents
{:ok, value} = SnmpKit.get("192.168.1.1", "sysDescr.0")
{:ok, results} = SnmpKit.walk("192.168.1.1", "system")
# MIB resolution
{:ok, oid} = SnmpKit.resolve("sysDescr.0")
Advanced Features
Engine Management and Performance
# Start the SNMP engine for advanced features
{:ok, _engine} = SnmpKit.SNMP.start_engine()
# Get performance statistics
{:ok, stats} = SnmpKit.SNMP.get_engine_stats()
# Batch operations for efficiency
requests = [
%{type: :get, target: "host1", oid: "sysDescr.0"},
%{type: :walk, target: "host2", oid: "interfaces"}
]
{:ok, results} = SnmpKit.SNMP.engine_batch(requests)
# Circuit breaker for reliability
{:ok, result} = SnmpKit.SNMP.with_circuit_breaker("unreliable.host", fn ->
SnmpKit.SNMP.get("unreliable.host", "sysDescr.0")
end)
Streaming and Large-Scale Operations
# Stream large walks to avoid memory issues
stream = SnmpKit.SNMP.walk_stream("192.168.1.1", "interfaces")
stream
|> Stream.take(1000)
|> Enum.to_list()
# Adaptive bulk operations that optimize themselves
{:ok, results} = SnmpKit.SNMP.adaptive_walk("192.168.1.1", "interfaces")
# Performance benchmarking
{:ok, benchmark} = SnmpKit.SNMP.benchmark_device("192.168.1.1", "system")
๐๏ธ Architecture
SnmpKit is organized into logical, discoverable modules:
SnmpKit.SNMP
- Complete SNMP protocol operations- Basic operations: get, set, walk, bulk
- Advanced features: streaming, async, multi-target
- Performance tools: engine, circuit breaker, metrics
- Pretty formatting and analysis
SnmpKit.MIB
- Comprehensive MIB management- OID resolution and reverse lookup
- MIB compilation and loading (both high-level and low-level)
- Tree navigation and analysis
- Standard and custom MIB support
SnmpKit.Sim
- Realistic device simulation- Profile-based device behavior
- Population management for testing
- Integration with test frameworks
SnmpKit
- Direct access for convenience- Common operations without module prefixes
- Backward compatibility for existing code
- Simple one-import access
๐ Enterprise Features
DOCSIS and Cable Modem Support
# DOCSIS-specific operations
{:ok, cm_status} = SnmpKit.SNMP.get("10.1.1.100", "docsIfCmtsServiceAdminStatus.1")
{:ok, signal_quality} = SnmpKit.SNMP.get("10.1.1.100", "docsIfSigQSignalNoise.1")
# Load DOCSIS MIBs
{:ok, _} = SnmpKit.MIB.compile("DOCS-CABLE-DEVICE-MIB.mib")
{:ok, _} = SnmpKit.MIB.compile("DOCS-IF-MIB.mib")
Network Monitoring Integration
# Monitor interface statistics
interface_oids = [
"ifInOctets.1", "ifOutOctets.1",
"ifInErrors.1", "ifOutErrors.1"
]
# Collect metrics from multiple devices
devices = ["router1", "router2", "switch1", "switch2"]
results =
for device <- devices,
oid <- interface_oids do
{device, oid, SnmpKit.SNMP.get(device, oid)}
end
# Analyze and format results
analysis = SnmpKit.SNMP.analyze_table(results)
๐งช Testing and Development
Simulated Devices for Testing
defmodule MyAppTest do
use ExUnit.Case
setup do
# Start a simulated device for testing
{:ok, profile} = SnmpKit.SnmpSim.ProfileLoader.load_profile(:generic_router)
{:ok, device} = SnmpKit.Sim.start_device(profile, port: 1161)
%{device: device, target: "127.0.0.1:1161"}
end
test "can query simulated device", %{target: target} do
{:ok, description} = SnmpKit.SNMP.get(target, "sysDescr.0")
assert description =~ "Simulated Router"
end
end
Performance Testing
# Benchmark different devices and operations
devices = ["fast.device", "slow.device", "unreliable.device"]
benchmarks =
for device <- devices do
SnmpKit.SNMP.benchmark_device(device, "system")
end
# Compare performance characteristics
for {device, {:ok, benchmark}} <- Enum.zip(devices, benchmarks) do
IO.puts "#{device}: avg=#{benchmark.avg_response_time}ms, success_rate=#{benchmark.success_rate}%"
end
๐ Documentation
- Full API Documentation - Complete function reference
- Livebook Tour - Interactive examples and tutorials
- Examples Directory - Practical usage examples
- MIB Guide - Working with MIBs and OID resolution
- Testing Guide - Testing strategies and simulated devices
๐ Migration from Other Libraries
From :snmp
(Erlang)
# Before (Erlang SNMP)
:snmp.sync_get(manager, oid, timeout)
# After (SnmpKit)
SnmpKit.SNMP.get("192.168.1.1", "sysDescr.0", timeout: 5000)
From Other Elixir SNMP Libraries
# SnmpKit provides more features with cleaner syntax
{:ok, results} = SnmpKit.SNMP.walk_multi([
{"host1", "interfaces"},
{"host2", "system"}
])
# Built-in formatting and analysis
{:ok, formatted} = SnmpKit.SNMP.walk_pretty("192.168.1.1", "interfaces")
โก Performance
SnmpKit is designed for high-performance network monitoring:
- Concurrent Operations - Efficient handling of thousands of simultaneous requests
- Bulk Operations - Optimized SNMP bulk protocols for large data sets
- Connection Pooling - Managed through the underlying SnmpLib layer
- Circuit Breakers - Automatic failure handling and recovery
- Streaming - Memory-efficient processing of large SNMP walks
- Adaptive Algorithms - Self-tuning bulk sizes and timeouts
๐ง Configuration
# config/config.exs
config :snmpkit,
default_community: "public",
default_timeout: 5000,
default_retries: 3,
default_version: :v2c
# For simulation
config :snmpkit, :simulation,
device_profiles_path: "priv/device_profiles",
walk_files_path: "priv/walks"
# For MIB management
config :snmpkit, :mib,
mib_path: ["priv/mibs", "/usr/share/snmp/mibs"],
auto_load_standard_mibs: true
๐ค Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Development Setup
git clone https://github.com/awksedgreep/snmpkit.git
cd snmpkit
mix deps.get
mix test
Running the Test Suite
# Run all tests
mix test
# Run with coverage
mix test --cover
# Run specific test categories
mix test --include docsis
mix test --include integration
๐ Roadmap
- ๐ SNMPv3 Support - Authentication and encryption
- ๐ IPv6 Enhancement - Full IPv6 support throughout
- ๐ Advanced Analytics - Built-in network analysis tools
- ๐ Plugin System - Custom protocol extensions
- ๐ฏ More Device Profiles - Extended simulation library
- ๐ฑ Management UI - Web interface for monitoring
๐ License
SnmpKit is released under the MIT License.
๐ Acknowledgments
- Built with โค๏ธ for the Elixir community
- Inspired by the need for modern, testable SNMP tools
- Thanks to all contributors and early adopters
Ready to simplify your SNMP operations? Get started with SnmpKit today! ๐
For questions, issues, or feature requests, please visit our GitHub repository.