CrackedRuby CrackedRuby

Network Devices (Router, Switch, Hub)

Overview

Network devices form the physical infrastructure that enables communication between computing systems. Routers, switches, and hubs operate at different network layers and serve distinct purposes in managing data transmission. Understanding these devices is essential for software developers working on distributed systems, network automation, infrastructure management, and applications that interact with network hardware.

A router operates at Layer 3 (Network Layer) and forwards packets between different networks based on IP addresses. Routers make intelligent decisions about the best path for data to reach its destination, handling traffic between separate network segments or connecting local networks to the internet.

A switch operates at Layer 2 (Data Link Layer) and forwards frames within a single network based on MAC addresses. Switches create dedicated paths between devices, enabling efficient communication within a local area network without the collision problems inherent in shared media.

A hub operates at Layer 1 (Physical Layer) and broadcasts all incoming data to every connected port. Hubs lack intelligence about where data should go, creating a shared collision domain where only one device can transmit at a time. Modern networks rarely use hubs due to their inefficiency.

Software developers interact with these devices through various protocols and APIs. Network management requires understanding device capabilities, configuration methods, and monitoring approaches. Applications that need to control or monitor network infrastructure must account for device-specific behaviors and limitations.

# Example: Basic network device information structure
class NetworkDevice
  attr_reader :ip_address, :mac_address, :device_type, :hostname
  
  def initialize(ip:, mac:, type:, hostname:)
    @ip_address = ip
    @mac_address = mac
    @device_type = type
    @hostname = hostname
  end
  
  def layer
    case device_type
    when :hub then 1
    when :switch then 2
    when :router then 3
    end
  end
end

router = NetworkDevice.new(
  ip: '192.168.1.1',
  mac: '00:1A:2B:3C:4D:5E',
  type: :router,
  hostname: 'gateway-01'
)
# => #<NetworkDevice @device_type=:router, @layer=3>

Key Principles

Network devices operate according to fundamental networking principles that determine how they process and forward traffic. Each device type has specific characteristics that define its behavior and appropriate use cases.

Layer-Based Operation: Network devices function at specific OSI model layers. Layer 1 devices (hubs) work with electrical signals and bits. Layer 2 devices (switches) work with frames and MAC addresses. Layer 3 devices (routers) work with packets and IP addresses. This layered approach determines what information a device uses to make forwarding decisions.

Collision Domains and Broadcast Domains: A collision domain is a network segment where data packets can collide during transmission. Hubs create a single large collision domain for all connected devices. Switches create separate collision domains for each port, eliminating collisions. Broadcast domains contain all devices that receive broadcast traffic. Switches forward broadcasts to all ports within a VLAN, while routers block broadcasts between networks.

MAC Address Learning: Switches build forwarding tables by observing source MAC addresses in received frames. When a frame arrives, the switch records which port received it and associates that port with the source MAC address. This learning process creates a map of which devices connect to which ports, enabling efficient frame forwarding without broadcasting.

Routing Tables and Path Selection: Routers maintain routing tables that map destination networks to next-hop addresses or outgoing interfaces. Routing protocols like OSPF, BGP, and RIP populate these tables automatically, or administrators configure static routes manually. When a packet arrives, the router examines the destination IP address and consults the routing table to determine the best forwarding path.

Store-and-Forward vs Cut-Through: Switches use different forwarding methods. Store-and-forward switches receive the entire frame, check for errors, then forward it. This method ensures error-free transmission but adds latency. Cut-through switches begin forwarding as soon as they read the destination MAC address, reducing latency but potentially propagating corrupted frames.

Network Address Translation (NAT): Routers perform NAT to allow multiple devices with private IP addresses to share a single public IP address. NAT modifies packet headers as traffic passes through the router, translating between private and public address spaces. This function is essential for IPv4 address conservation and network security.

Spanning Tree Protocol: Networks with multiple switches can create loops where traffic circulates indefinitely. The Spanning Tree Protocol (STP) prevents loops by logically blocking redundant paths while maintaining backup routes. If the active path fails, STP activates a backup path to restore connectivity.

Quality of Service (QoS): Network devices prioritize different types of traffic to ensure critical applications receive necessary bandwidth and low latency. QoS mechanisms include traffic classification, queueing, and policing. Routers and managed switches implement QoS policies to differentiate between voice, video, and data traffic.

Implementation Approaches

Managing network devices requires different strategies depending on scale, automation requirements, and infrastructure complexity. Each approach offers specific advantages for different operational contexts.

Command-Line Interface Management: Network devices expose CLI interfaces through SSH or Telnet connections. Administrators send text commands to configure interfaces, routing protocols, VLANs, and security policies. This approach provides direct control and works universally across vendors, though it requires parsing text output and lacks standardization across different platforms.

# Conceptual CLI interaction pattern
require 'net/ssh'

class DeviceCLI
  def initialize(host, username, password)
    @host = host
    @username = username
    @password = password
  end
  
  def execute_command(command)
    output = ""
    Net::SSH.start(@host, @username, password: @password) do |ssh|
      output = ssh.exec!(command)
    end
    output
  end
  
  def get_interface_status
    output = execute_command("show interface status")
    parse_interface_output(output)
  end
  
  private
  
  def parse_interface_output(text)
    # Parse device-specific text output
    interfaces = []
    text.each_line do |line|
      if line =~ /^(\w+\d+\/\d+)\s+(\w+)/
        interfaces << { name: $1, status: $2 }
      end
    end
    interfaces
  end
end

SNMP Monitoring and Configuration: Simple Network Management Protocol provides standardized access to device metrics and configuration. SNMP uses a management information base (MIB) that defines available data objects. Network monitoring systems poll devices for statistics like interface utilization, error rates, and CPU load. SNMP traps send alerts when specific conditions occur.

REST API Integration: Modern network devices offer RESTful APIs that return structured JSON or XML data. API-based management eliminates text parsing complexity and provides programmatic access to all device features. This approach scales well for automation and integrates naturally with modern orchestration systems.

# REST API interaction pattern
require 'net/http'
require 'json'

class DeviceAPI
  def initialize(base_url, api_token)
    @base_url = base_url
    @api_token = api_token
  end
  
  def get_interfaces
    uri = URI("#{@base_url}/api/v1/interfaces")
    request = Net::HTTP::Get.new(uri)
    request['Authorization'] = "Bearer #{@api_token}"
    request['Content-Type'] = 'application/json'
    
    response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
    
    JSON.parse(response.body)
  end
  
  def configure_interface(interface_name, config)
    uri = URI("#{@base_url}/api/v1/interfaces/#{interface_name}")
    request = Net::HTTP::Put.new(uri)
    request['Authorization'] = "Bearer #{@api_token}"
    request['Content-Type'] = 'application/json'
    request.body = config.to_json
    
    response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
    
    response.code == '200'
  end
end

api = DeviceAPI.new('https://router.example.com', 'token123')
interfaces = api.get_interfaces
# => [{"name"=>"eth0", "status"=>"up", "speed"=>"1000"}]

Network Configuration Management Systems: Dedicated configuration management tools like Ansible, Puppet, and Chef provide declarative approaches to device management. These systems define desired states rather than imperative commands, handle idempotency, and maintain configuration version control. They abstract vendor-specific differences through modules and plugins.

Controller-Based SDN Approaches: Software-Defined Networking separates the control plane from the data plane. Centralized controllers make routing and forwarding decisions, pushing flow rules to network devices. SDN enables dynamic network reconfiguration, traffic engineering, and programmatic network control through northbound APIs.

Ruby Implementation

Ruby applications interact with network devices through various gems and libraries that abstract protocol complexity. Different gems target specific use cases from simple SNMP polling to comprehensive device automation.

SNMP Operations: The snmp gem provides Ruby bindings for SNMP operations. Applications can retrieve device metrics, monitor interface statistics, and receive trap notifications. SNMP v2c uses community strings for authentication, while SNMP v3 adds encryption and user-based security.

require 'snmp'

class NetworkMonitor
  def initialize(host, community = 'public')
    @host = host
    @community = community
  end
  
  def get_system_info
    SNMP::Manager.open(host: @host, community: @community) do |manager|
      response = manager.get([
        'sysDescr.0',
        'sysUpTime.0',
        'sysName.0'
      ])
      
      response.each_varbind do |vb|
        puts "#{vb.name}: #{vb.value}"
      end
    end
  end
  
  def get_interface_stats(interface_index)
    SNMP::Manager.open(host: @host, community: @community) do |manager|
      response = manager.get([
        "ifDescr.#{interface_index}",
        "ifInOctets.#{interface_index}",
        "ifOutOctets.#{interface_index}",
        "ifSpeed.#{interface_index}"
      ])
      
      stats = {}
      response.each_varbind do |vb|
        oid_parts = vb.name.to_s.split('.')
        metric = oid_parts[0]
        stats[metric] = vb.value.to_s
      end
      stats
    end
  end
  
  def walk_interface_table
    interfaces = []
    SNMP::Manager.open(host: @host, community: @community) do |manager|
      manager.walk('ifDescr') do |row|
        row.each do |vb|
          index = vb.name.to_s.split('.').last
          interfaces << {
            index: index,
            description: vb.value.to_s
          }
        end
      end
    end
    interfaces
  end
end

monitor = NetworkMonitor.new('192.168.1.1')
stats = monitor.get_interface_stats(1)
# => {"ifDescr"=>"eth0", "ifInOctets"=>"12345678", ...}

SSH-Based Configuration: The net-ssh gem enables Ruby applications to establish SSH connections and execute commands on network devices. Applications send configuration commands, retrieve output, and parse responses. This approach works with any device supporting SSH regardless of vendor.

require 'net/ssh'

class RouterConfig
  def initialize(host, username, password)
    @host = host
    @username = username
    @password = password
  end
  
  def configure_interface(interface, ip_address, subnet_mask)
    commands = [
      "configure terminal",
      "interface #{interface}",
      "ip address #{ip_address} #{subnet_mask}",
      "no shutdown",
      "end",
      "write memory"
    ]
    
    output = execute_commands(commands)
    output.include?("Building configuration")
  end
  
  def add_static_route(network, mask, next_hop)
    commands = [
      "configure terminal",
      "ip route #{network} #{mask} #{next_hop}",
      "end",
      "write memory"
    ]
    
    execute_commands(commands)
  end
  
  def get_running_config
    execute_command("show running-config")
  end
  
  private
  
  def execute_commands(command_list)
    full_output = ""
    Net::SSH.start(@host, @username, password: @password) do |ssh|
      command_list.each do |cmd|
        output = ssh.exec!(cmd)
        full_output += output
      end
    end
    full_output
  end
  
  def execute_command(command)
    Net::SSH.start(@host, @username, password: @password) do |ssh|
      ssh.exec!(command)
    end
  end
end

router = RouterConfig.new('192.168.1.1', 'admin', 'password')
router.configure_interface('GigabitEthernet0/1', '10.0.1.1', '255.255.255.0')
router.add_static_route('10.0.2.0', '255.255.255.0', '10.0.1.254')

HTTP API Clients: Network devices with REST APIs accept HTTP requests with JSON payloads. Ruby's net/http library or gems like httparty and faraday simplify API interactions. Applications authenticate with tokens or certificates, send configuration changes, and receive structured responses.

require 'httparty'

class SwitchAPI
  include HTTParty
  base_uri 'https://switch.example.com/api'
  
  def initialize(api_key)
    @options = {
      headers: {
        'Authorization' => "Bearer #{api_key}",
        'Content-Type' => 'application/json'
      },
      verify: false  # For testing only - verify certs in production
    }
  end
  
  def create_vlan(vlan_id, name)
    body = {
      vlan_id: vlan_id,
      name: name
    }.to_json
    
    response = self.class.post('/vlans', @options.merge(body: body))
    response.success?
  end
  
  def assign_vlan_to_port(port, vlan_id)
    body = {
      access_vlan: vlan_id,
      mode: 'access'
    }.to_json
    
    response = self.class.put("/interfaces/#{port}", @options.merge(body: body))
    response.success?
  end
  
  def get_port_statistics(port)
    response = self.class.get("/interfaces/#{port}/statistics", @options)
    
    if response.success?
      JSON.parse(response.body)
    else
      nil
    end
  end
  
  def get_mac_address_table
    response = self.class.get('/mac-address-table', @options)
    
    if response.success?
      JSON.parse(response.body)
    else
      []
    end
  end
end

switch = SwitchAPI.new('api-key-here')
switch.create_vlan(100, 'Production')
switch.assign_vlan_to_port('eth1/0/1', 100)
stats = switch.get_port_statistics('eth1/0/1')
# => {"rx_bytes"=>123456, "tx_bytes"=>789012, ...}

Device Discovery and Scanning: Ruby applications can discover network devices through ARP table examination, LLDP protocol parsing, or active scanning. The ruby-nmap gem wraps the nmap network scanner for device discovery and port scanning.

require 'nmap/command'

class NetworkDiscovery
  def initialize(subnet)
    @subnet = subnet
  end
  
  def discover_devices
    devices = []
    
    Nmap::Command.run do |nmap|
      nmap.targets = @subnet
      nmap.verbose = false
      nmap.xml = 'scan_results.xml'
      
      nmap.each_host do |host|
        devices << {
          ip: host.ip,
          hostname: host.hostname,
          status: host.status,
          ports: extract_ports(host)
        }
      end
    end
    
    devices
  end
  
  def identify_network_devices(devices)
    devices.select do |device|
      # Common network device ports
      has_network_ports = device[:ports].any? do |port|
        [22, 23, 80, 443, 161, 830].include?(port[:number])
      end
      
      has_network_ports
    end
  end
  
  private
  
  def extract_ports(host)
    ports = []
    host.each_port do |port|
      ports << {
        number: port.number,
        protocol: port.protocol,
        state: port.state,
        service: port.service
      }
    end
    ports
  end
end

discovery = NetworkDiscovery.new('192.168.1.0/24')
all_devices = discovery.discover_devices
network_devices = discovery.identify_network_devices(all_devices)
# => [{ip: "192.168.1.1", hostname: "router.local", ...}]

Practical Examples

Network device interaction patterns vary based on operational requirements. These examples demonstrate common scenarios developers encounter when building network automation or monitoring systems.

Monitoring Interface Status: Applications periodically check interface operational status to detect failures or degradation. This pattern collects statistics, identifies anomalies, and triggers alerts when thresholds exceed acceptable values.

class InterfaceMonitor
  def initialize(device)
    @device = device
    @baseline = {}
  end
  
  def establish_baseline
    stats = @device.get_all_interfaces
    
    stats.each do |interface|
      @baseline[interface[:name]] = {
        rx_rate: interface[:rx_bytes_per_sec],
        tx_rate: interface[:tx_bytes_per_sec],
        errors: interface[:errors],
        drops: interface[:drops]
      }
    end
  end
  
  def check_for_anomalies
    current = @device.get_all_interfaces
    anomalies = []
    
    current.each do |interface|
      name = interface[:name]
      baseline = @baseline[name]
      
      next unless baseline
      
      # Check for elevated error rates
      if interface[:errors] > baseline[:errors] * 2
        anomalies << {
          interface: name,
          type: :error_rate,
          baseline: baseline[:errors],
          current: interface[:errors]
        }
      end
      
      # Check for unexpected utilization drops
      if interface[:rx_rate] < baseline[:rx_rate] * 0.5 && baseline[:rx_rate] > 1000
        anomalies << {
          interface: name,
          type: :utilization_drop,
          baseline: baseline[:rx_rate],
          current: interface[:rx_rate]
        }
      end
      
      # Check for link status changes
      if interface[:status] == 'down' && baseline[:status] == 'up'
        anomalies << {
          interface: name,
          type: :link_down,
          message: "Interface went down"
        }
      end
    end
    
    anomalies
  end
  
  def generate_alert(anomalies)
    return if anomalies.empty?
    
    anomalies.each do |anomaly|
      puts "ALERT: #{anomaly[:interface]} - #{anomaly[:type]}"
      puts "  Details: #{anomaly}"
    end
  end
end

Automated VLAN Provisioning: Networks with dynamic requirements need programmatic VLAN creation and assignment. This pattern creates VLANs, assigns ports, and configures trunking across multiple switches.

class VLANProvisioner
  def initialize(switches)
    @switches = switches
  end
  
  def provision_vlan(vlan_id, vlan_name, access_ports, trunk_ports)
    results = []
    
    @switches.each do |switch|
      result = {
        switch: switch.hostname,
        vlan_created: false,
        access_ports_configured: [],
        trunk_ports_configured: []
      }
      
      # Create VLAN on switch
      if switch.create_vlan(vlan_id, vlan_name)
        result[:vlan_created] = true
      end
      
      # Configure access ports
      access_ports.each do |port|
        if switch.configure_access_port(port, vlan_id)
          result[:access_ports_configured] << port
        end
      end
      
      # Configure trunk ports to carry this VLAN
      trunk_ports.each do |port|
        if switch.add_vlan_to_trunk(port, vlan_id)
          result[:trunk_ports_configured] << port
        end
      end
      
      results << result
    end
    
    results
  end
  
  def deprovision_vlan(vlan_id)
    @switches.each do |switch|
      # Remove VLAN from all trunk ports first
      switch.get_trunk_ports.each do |port|
        switch.remove_vlan_from_trunk(port, vlan_id)
      end
      
      # Remove access port assignments
      switch.get_ports_by_vlan(vlan_id).each do |port|
        switch.configure_access_port(port, 1)  # Move to default VLAN
      end
      
      # Delete VLAN
      switch.delete_vlan(vlan_id)
    end
  end
  
  def verify_vlan_consistency(vlan_id)
    inconsistencies = []
    
    vlan_configs = @switches.map do |switch|
      {
        switch: switch.hostname,
        vlan_exists: switch.vlan_exists?(vlan_id),
        access_ports: switch.get_ports_by_vlan(vlan_id),
        trunk_ports: switch.get_trunk_ports_with_vlan(vlan_id)
      }
    end
    
    # Check if VLAN exists on all switches
    missing_vlan = vlan_configs.select { |config| !config[:vlan_exists] }
    if missing_vlan.any?
      inconsistencies << {
        type: :missing_vlan,
        switches: missing_vlan.map { |c| c[:switch] }
      }
    end
    
    # Check for orphaned access ports (VLAN on one switch but not others)
    vlan_configs.each do |config|
      if config[:access_ports].any? && !config[:vlan_exists]
        inconsistencies << {
          type: :orphaned_ports,
          switch: config[:switch],
          ports: config[:access_ports]
        }
      end
    end
    
    inconsistencies
  end
end

Router Failover Detection: Applications monitor router availability and routing table changes to detect failover events. This pattern tracks active routes, identifies when backup paths activate, and measures convergence time.

class RouterFailoverMonitor
  def initialize(primary_router, backup_router)
    @primary = primary_router
    @backup = backup_router
    @state = :primary_active
    @failover_events = []
  end
  
  def check_router_state
    primary_up = router_reachable?(@primary)
    backup_up = router_reachable?(@backup)
    
    new_state = determine_state(primary_up, backup_up)
    
    if new_state != @state
      record_state_change(@state, new_state)
      @state = new_state
    end
    
    @state
  end
  
  def verify_routing_convergence(destination_network)
    primary_route = @primary.get_route(destination_network)
    backup_route = @backup.get_route(destination_network)
    
    {
      primary: {
        reachable: !primary_route.nil?,
        next_hop: primary_route&.next_hop,
        metric: primary_route&.metric
      },
      backup: {
        reachable: !backup_route.nil?,
        next_hop: backup_route&.next_hop,
        metric: backup_route&.metric
      },
      converged: routes_match?(primary_route, backup_route)
    }
  end
  
  def measure_failover_time(test_interval = 1)
    start_time = Time.now
    
    # Force primary router down (in test environment)
    simulate_failure(@primary)
    
    # Wait for backup to converge
    until backup_has_route?
      sleep test_interval
      break if (Time.now - start_time) > 60  # Timeout after 60 seconds
    end
    
    convergence_time = Time.now - start_time
    
    {
      convergence_time: convergence_time,
      within_target: convergence_time < 10,  # Target: 10 seconds
      events: @failover_events
    }
  end
  
  private
  
  def router_reachable?(router)
    system("ping -c 1 -W 1 #{router.ip_address} > /dev/null 2>&1")
  end
  
  def determine_state(primary_up, backup_up)
    case [primary_up, backup_up]
    when [true, true] then :both_active
    when [true, false] then :primary_active
    when [false, true] then :backup_active
    when [false, false] then :both_down
    end
  end
  
  def record_state_change(old_state, new_state)
    @failover_events << {
      timestamp: Time.now,
      from: old_state,
      to: new_state
    }
  end
  
  def routes_match?(route1, route2)
    return false if route1.nil? || route2.nil?
    route1.next_hop == route2.next_hop
  end
  
  def backup_has_route?
    @backup.get_default_route&.active?
  end
end

MAC Address Table Management: Switches maintain MAC address tables that map hardware addresses to physical ports. Applications query these tables for device location tracking, security monitoring, and troubleshooting.

class MACTableAnalyzer
  def initialize(switch)
    @switch = switch
  end
  
  def find_device_location(mac_address)
    mac_table = @switch.get_mac_table
    
    entry = mac_table.find { |e| e[:mac] == mac_address }
    
    return nil unless entry
    
    {
      mac_address: entry[:mac],
      port: entry[:port],
      vlan: entry[:vlan],
      type: entry[:type],  # dynamic or static
      last_seen: entry[:age]
    }
  end
  
  def detect_mac_flapping
    # MAC flapping occurs when same MAC appears on multiple ports
    mac_table = @switch.get_mac_table
    mac_by_port = Hash.new { |h, k| h[k] = [] }
    
    mac_table.each do |entry|
      mac_by_port[entry[:mac]] << entry[:port]
    end
    
    flapping = mac_by_port.select { |mac, ports| ports.uniq.length > 1 }
    
    flapping.map do |mac, ports|
      {
        mac_address: mac,
        ports: ports.uniq,
        likely_cause: diagnose_flapping(ports.uniq)
      }
    end
  end
  
  def identify_security_violations(authorized_macs)
    mac_table = @switch.get_mac_table
    
    unauthorized = mac_table.reject do |entry|
      authorized_macs.include?(entry[:mac])
    end
    
    unauthorized.map do |entry|
      {
        mac_address: entry[:mac],
        port: entry[:port],
        vlan: entry[:vlan],
        first_seen: entry[:age],
        risk_level: assess_risk(entry)
      }
    end
  end
  
  def track_device_mobility(mac_address, interval = 60)
    locations = []
    
    loop do
      location = find_device_location(mac_address)
      
      if location
        locations << {
          timestamp: Time.now,
          port: location[:port],
          vlan: location[:vlan]
        }
        
        # Check if device moved
        if locations.length > 1
          previous = locations[-2]
          current = locations[-1]
          
          if previous[:port] != current[:port]
            puts "Device moved: #{previous[:port]} -> #{current[:port]}"
          end
        end
      end
      
      sleep interval
    end
  end
  
  private
  
  def diagnose_flapping(ports)
    if ports.length == 2
      :possible_loop
    elsif ports.length > 2
      :spanning_tree_issue
    else
      :unknown
    end
  end
  
  def assess_risk(entry)
    # Example risk assessment logic
    if entry[:vlan] == 1  # Default VLAN
      :medium
    elsif entry[:port].start_with?('Gig')  # Trunk port
      :high
    else
      :low
    end
  end
end

Tools & Ecosystem

Network device management requires specialized tools and libraries that handle protocol complexity and vendor-specific behaviors. The Ruby ecosystem provides gems for various network management tasks.

SNMP Libraries: The snmp gem implements SNMP v1, v2c, and v3 protocols. It provides synchronous and asynchronous operations, bulk requests, and trap handling. Applications use SNMP for monitoring, threshold-based alerting, and metric collection.

# Advanced SNMP monitoring with bulk requests
require 'snmp'

class SNMPBulkMonitor
  def initialize(hosts, community)
    @hosts = hosts
    @community = community
  end
  
  def bulk_collect_interface_stats
    results = {}
    
    @hosts.each do |host|
      SNMP::Manager.open(host: host, community: @community) do |manager|
        # Bulk request for efficiency
        response = manager.get_bulk(0, 10, [
          'ifDescr',
          'ifInOctets',
          'ifOutOctets',
          'ifInErrors',
          'ifOutErrors'
        ])
        
        results[host] = process_bulk_response(response)
      end
    end
    
    results
  end
  
  private
  
  def process_bulk_response(response)
    interfaces = Hash.new { |h, k| h[k] = {} }
    
    response.each_varbind do |vb|
      oid_parts = vb.name.to_s.split('.')
      metric_name = oid_parts[0]
      interface_index = oid_parts[-1]
      
      interfaces[interface_index][metric_name] = vb.value.to_s
    end
    
    interfaces
  end
end

SSH and Telnet Libraries: Net::SSH handles encrypted connections to network devices. Net::Telnet provides fallback for older equipment without SSH support. These gems support interactive sessions, command execution, and output parsing.

REST API Clients: HTTParty and Faraday simplify HTTP API interactions. These gems handle authentication, request formatting, response parsing, and error handling. They support both synchronous and asynchronous operations.

Network Analysis Tools: PacketFu creates and parses network packets at the protocol level. RubyNetworkMap generates network topology diagrams from device data. These tools assist with network discovery and documentation.

Configuration Management Integration: Knife plugins for Chef and Ansible modules written in Ruby enable network device configuration through existing automation frameworks. These integrations apply configuration management principles to network infrastructure.

Monitoring and Alerting: The prometheus-client gem exports network metrics to Prometheus monitoring systems. Telegraf plugins written in Ruby collect device statistics and forward them to time-series databases.

Integration & Interoperability

Network devices integrate with software systems through standardized protocols and APIs. Applications must account for vendor differences, protocol limitations, and operational constraints.

Multi-Vendor Environments: Different manufacturers implement protocols differently. Cisco IOS, Juniper JunOS, and Arista EOS use distinct CLI syntaxes despite serving similar functions. Applications handle vendor variations through abstraction layers or device-specific adapters.

class DeviceFactory
  def self.create(host, type, credentials)
    case type
    when :cisco
      CiscoDevice.new(host, credentials)
    when :juniper
      JuniperDevice.new(host, credentials)
    when :arista
      AristaDevice.new(host, credentials)
    else
      GenericDevice.new(host, credentials)
    end
  end
end

class CiscoDevice
  def configure_interface(interface, ip, mask)
    commands = [
      "configure terminal",
      "interface #{interface}",
      "ip address #{ip} #{mask}",
      "no shutdown",
      "end"
    ]
    execute_commands(commands)
  end
end

class JuniperDevice
  def configure_interface(interface, ip, mask)
    prefix_length = mask_to_prefix(mask)
    commands = [
      "configure",
      "set interfaces #{interface} unit 0 family inet address #{ip}/#{prefix_length}",
      "commit"
    ]
    execute_commands(commands)
  end
  
  private
  
  def mask_to_prefix(mask)
    # Convert 255.255.255.0 to 24
    mask.split('.').map(&:to_i).map { |o| o.to_s(2) }.join.count('1')
  end
end

Protocol Translation: Applications convert between different management protocols. An API gateway might expose REST endpoints that translate to SNMP or CLI commands. This pattern enables modern applications to interact with legacy devices.

Event Stream Integration: Network devices generate events for link state changes, threshold violations, and security incidents. Applications consume these events through SNMP traps, syslog messages, or streaming telemetry APIs. Event processing systems correlate device events with application metrics for comprehensive monitoring.

Configuration Synchronization: Networks with redundant devices require configuration consistency. Applications maintain configuration repositories, detect drift, and reconcile differences. Version control systems track configuration changes and enable rollback.

Orchestration Integration: Container orchestration platforms like Kubernetes integrate with network devices for service mesh implementations and load balancing. SDN controllers receive service deployment events and configure network paths automatically.

Reference

Device Type Comparison

Feature Hub Switch Router
OSI Layer 1 (Physical) 2 (Data Link) 3 (Network)
Forwarding Basis None (broadcasts all) MAC address IP address
Collision Domains Single shared domain Per-port isolation Separates networks
Broadcast Domains Single domain Single per VLAN Separates domains
Intelligence No decision-making MAC learning Routing decisions
Typical Use Legacy/obsolete LAN switching Inter-network routing
Throughput Limited by collision Full duplex per port Limited by routing

Common Management Protocols

Protocol Port Purpose Authentication
SSH 22 Encrypted CLI access Username/password, keys
Telnet 23 Unencrypted CLI access Username/password
SNMP v2c 161 Monitoring/management Community string
SNMP v3 161 Secure monitoring User-based, encrypted
HTTP/HTTPS 80/443 Web interface Username/password, tokens
NETCONF 830 XML-based config SSH-based auth
RESTCONF 443 RESTful config HTTPS-based auth
Syslog 514 Event logging None (UDP)

Ruby Gem Reference

Gem Purpose Key Features
snmp SNMP protocol implementation v1/v2c/v3, walks, traps
net-ssh SSH client Command execution, file transfer
net-telnet Telnet client Legacy device access
httparty HTTP API client REST API interaction
ruby-nmap Network scanning Device discovery
packetfu Packet crafting Protocol-level access

Standard SNMP OIDs

OID Description Type
1.3.6.1.2.1.1.1.0 sysDescr - System description String
1.3.6.1.2.1.1.3.0 sysUpTime - System uptime TimeTicks
1.3.6.1.2.1.1.5.0 sysName - System name String
1.3.6.1.2.1.2.2.1.2 ifDescr - Interface description String
1.3.6.1.2.1.2.2.1.8 ifOperStatus - Interface status Integer
1.3.6.1.2.1.2.2.1.10 ifInOctets - Bytes received Counter
1.3.6.1.2.1.2.2.1.16 ifOutOctets - Bytes transmitted Counter
1.3.6.1.2.1.2.2.1.14 ifInErrors - Input errors Counter

Common Port Assignments

Service Port Protocol Purpose
FTP Data 20 TCP File transfer data
FTP Control 21 TCP File transfer commands
SSH 22 TCP Secure shell
Telnet 23 TCP Remote terminal
SMTP 25 TCP Email transmission
DNS 53 TCP/UDP Name resolution
HTTP 80 TCP Web traffic
HTTPS 443 TCP Secure web traffic
SNMP 161 UDP Network management
SNMP Trap 162 UDP SNMP notifications

Router Configuration Checklist

Task Configuration Item Verification Command
Hostname Device identification show running-config
Interfaces IP addressing, masks show ip interface brief
Routing Static or dynamic routes show ip route
NAT Address translation show ip nat translations
ACLs Access control lists show access-lists
DHCP Address assignment show ip dhcp binding
DNS Name resolution show hosts
Time NTP synchronization show ntp status

Switch Configuration Checklist

Task Configuration Item Verification Command
Hostname Device identification show running-config
VLANs Virtual LAN creation show vlan brief
Trunk Ports Inter-switch links show interfaces trunk
Access Ports End device ports show interfaces status
STP Spanning tree show spanning-tree
Port Security MAC filtering show port-security
SNMP Monitoring access show snmp
Management IP Remote access show ip interface

Interface Status Values

Status Description Typical Cause
up/up Line and protocol up Normal operation
up/down Line up, protocol down Layer 2 issue, encapsulation
down/down Line and protocol down Cable disconnected, shutdown
administratively down Interface disabled Manual shutdown
err-disabled Error condition Port security, BPDU guard