🔍 Network Interface Monitoring Tool

Complete Guide for RTNetlink Interface Query System

📋 Overview

This tool provides comprehensive network interface monitoring and analysis using Linux RTNetlink and Generic Netlink protocols. It leverages CFFI (C Foreign Function Interface) to directly interface with kernel networking subsystems, offering detailed insights into network configurations, addresses, and specialized interface types.

Key Capabilities:
  • Real-time network interface status monitoring
  • Complete IP address information including IPv6 DAD states
  • Bridge configuration and STP details
  • WireGuard VPN interface monitoring via Generic Netlink
  • VLAN, veth, and GENEVE virtual interface support
  • Hardware offload capabilities detection
  • DPLL (Digital Phase-Locked Loop) pin synchronization info

Why This Tool?

Traditional tools like ip and ifconfig provide basic interface information, but this tool offers:

💾 Installation

System Requirements

Component Version Status
Python 3.8 or higher Required
Linux Kernel 2.6+ (5.0+ recommended) Required
CFFI 1.0.0 or higher Required
setuptools Latest Required (Python 3.12+)
Root/sudo access - Required

Quick Installation

$ pip install cffi setuptools

Or for system-wide installation:

$ sudo pip3 install cffi setuptools

Verification

Verify your Python version:

$ python3 --version
Python 3.8.0 (or higher)

Check if CFFI is installed:

$ python3 -c "import cffi; print(cffi.__version__)"
1.15.0
⚠️ Python 3.12+ Notice:
Python 3.12 and higher require setuptools to be explicitly installed for CFFI to work properly. The script will check for this and provide a clear error message if it's missing.

File Setup

  1. Save the script as device_info.py
  2. Make it executable:
    $ chmod +x device_info.py
  3. Verify it runs:
    $ sudo python3 device_info.py --help

🚀 Usage

Basic Usage Patterns

1. Full JSON Output (Default)

Get complete interface information in JSON format:

$ sudo python3 device_info.py

This outputs a comprehensive JSON structure containing all detected interfaces, their configurations, addresses, and special attributes.

2. Extended Interface Details

Show human-readable interface information with extensive details:

$ sudo python3 device_info.py --extended

Output includes:

3. Detailed Address Information

Focus on IP address configuration and readiness:

$ sudo python3 device_info.py --addresses

Shows address-specific details:

4. WireGuard Interfaces Only

Filter output to show only WireGuard interfaces with peer details:

$ sudo python3 device_info.py --wireguard

Displays:

5. Summary View

Condensed view of special interfaces (bridges, VLANs, WireGuard, veth):

$ sudo python3 device_info.py --summary
💡 Pro Tip: Pipe JSON output to jq for advanced filtering:
$ sudo python3 device_info.py | jq '.eth0.addresses'

Common Use Cases

Monitoring IPv6 Address Configuration

# Check if IPv6 addresses have completed DAD
$ sudo python3 device_info.py --addresses | grep -A 10 "ipv6"

# Get readiness status of all addresses
$ sudo python3 device_info.py | jq '.[] | .addresses[] | {addr: .address, ready: .readiness}'

Bridge Management

# View all bridge configurations
$ sudo python3 device_info.py --summary | grep -i bridge

# Get detailed bridge STP status
$ sudo python3 device_info.py --extended | grep -A 20 "Bridge Master"

WireGuard Monitoring

# Check WireGuard peer status
$ sudo python3 device_info.py --wireguard

# Monitor peer handshakes
$ sudo python3 device_info.py | jq '.wg0.wireguard.peers[] | {endpoint: .endpoint, handshake: .latest_handshake_str}'

Automated Monitoring

#!/bin/bash
# Monitor for interface changes every 5 seconds

while true; do
    sudo python3 device_info.py > /tmp/interfaces_new.json
    if ! diff -q /tmp/interfaces_old.json /tmp/interfaces_new.json &>/dev/null; then
        echo "$(date): Interface configuration changed"
        diff /tmp/interfaces_old.json /tmp/interfaces_new.json
    fi
    mv /tmp/interfaces_new.json /tmp/interfaces_old.json
    sleep 5
done

✨ Features

🔗 RTNetlink Integration

Direct kernel interface using RTM_GETLINK and RTM_GETADDR messages for low-level network configuration access.

🔐 WireGuard Support

Generic Netlink integration provides detailed WireGuard interface information including peer configurations and statistics.

🌉 Bridge Monitoring

Complete bridge configuration including STP state, VLAN filtering, multicast snooping, and port attributes.

📡 Address Readiness

Smart address state computation considering IPv6 DAD, interface operational state, and address flags.

⚡ Hardware Offload

Detection and reporting of GSO, GRO, TSO capabilities and limits for network performance tuning.

🏷️ VLAN & Virtual Interfaces

Support for VLAN, veth, GENEVE, and other virtual interface types with detailed configuration.

🎯 DPLL Synchronization

Hardware time synchronization information including pin types, states, and frequency adjustments.

📊 Comprehensive Statistics

Interface counters, carrier changes, multicast groups, and historical event tracking.

Supported Interface Types

Interface Type Support Level Key Features
Physical (eth*, enp*) Full Hardware offload, carrier detection, statistics
Bridge (br*) Full STP, VLAN filtering, multicast, port configuration
WireGuard (wg*) Full Peers, allowed IPs, handshakes, transfer stats
VLAN (*.*, vlan*) Full VLAN ID, protocol, parent interface
veth Full Peer interface detection
GENEVE Full VNI, remote endpoint, port configuration
Loopback (lo) Full Standard interface attributes
Bonding (bond*) Partial Basic interface info, slave detection

Comprehensive Attribute Decoding

The tool decodes 64+ IFLA attributes and 11+ IFA attributes, including:

IFLA (Interface Link Attributes)

IFA (Interface Address Attributes)

🏗️ Architecture

System Design

The tool uses a layered architecture to interact with the Linux kernel:

┌─────────────────────────────────────────┐
│          Python Application             │
│  (Argument Parsing, JSON Output, etc.)  │
└────────────────┬────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────┐
│          CFFI Interface Layer           │
│     (Python ↔ C Type Conversion)        │
└────────────────┬────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────┐
│          C Library Functions            │
│  - create_rtnetlink_socket()            │
│  - query_links()                        │
│  - query_addresses()                    │
│  - query_wireguard_info()               │
│  - parse_ifla_attributes()              │
└────────────────┬────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────┐
│         Linux Kernel Netlink            │
│  RTNetlink  │  Generic Netlink          │
│  (RTM_*)    │  (GENL_*)                 │
└─────────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────┐
│         Network Subsystem               │
│  Interfaces, Addresses, Routing, etc.   │
└─────────────────────────────────────────┘

Key Components

1. C Library Integration (Lines 57-5100)

Comprehensive C code embedded in Python that handles:

2. CFFI Builder (Lines 5102-5150)

Dynamic compilation of C code with Python binding generation:

ffi = FFI()
ffi.cdef("""
    typedef struct { ... } response_buffer_t;
    int create_rtnetlink_socket(void);
    // ... function declarations
""")

# Compile C code at runtime
lib = ffi.verify(C_SOURCE, libraries=[], extra_compile_args=['-O2'])

3. Python Interface Layer (Lines 5150-5300)

High-level functions that:

4. Output Formatters (Lines 5400-5750)

Multiple presentation modes:

Data Flow

  1. Initialization: CFFI compiles C code and creates Python bindings
  2. Socket Creation: Opens Netlink socket with appropriate protocols
  3. Query Dispatch: Sends RTM_GETLINK and RTM_GETADDR requests
  4. Kernel Response: Receives and buffers Netlink messages
  5. Attribute Parsing: Decodes nested TLV (Type-Length-Value) structures
  6. JSON Assembly: C code builds JSON strings for easy Python consumption
  7. Python Processing: Enriches data with computed fields
  8. Output Generation: Formats according to user-selected mode

Memory Management

Safety Features:
  • Response buffers automatically grow to accommodate large messages
  • Buffer capacity is tracked and never exceeded
  • All C-allocated memory is properly freed
  • CFFI handles Python ↔ C memory lifetime correctly

Attribute Decoding Strategy

The tool employs a comprehensive attribute decoding system:

  1. Known Attributes: Explicitly decoded with proper type handling
  2. Nested Attributes: Recursively parsed (e.g., IFLA_LINKINFO, IFLA_AF_SPEC)
  3. Binary Data: Base64-encoded or hex-formatted for safe transport
  4. Unknown Attributes: Recorded but not fully decoded
  5. Type-Specific: Bridge, WireGuard, VLAN use specialized decoders

🔧 Maintenance

Regular Maintenance Tasks

1. Update Dependency Versions

# Update CFFI
$ pip install --upgrade cffi

# Update setuptools (Python 3.12+)
$ pip install --upgrade setuptools

# Verify versions
$ pip list | grep -E "(cffi|setuptools)"

2. Check Kernel Compatibility

When upgrading your kernel, verify that new attributes are properly supported:

# Check kernel version
$ uname -r

# Test the script
$ sudo python3 device_info.py --extended

# Look for "unknown_attrs" in output
$ sudo python3 device_info.py | jq '.[] | select(.unknown_attrs != null)'

3. Monitor for Deprecation Warnings

# Run with warnings enabled
$ python3 -W all device_info.py > /dev/null

Extending the Tool

Adding New IFLA Attributes

When new kernel versions introduce new IFLA_* constants:

  1. Find the constant definition in /usr/include/linux/if_link.h
  2. Add it to the C code's IFLA_ATTR_NAMES array (around line 300)
  3. Implement decoding logic in parse_ifla_attributes() (around line 1500)
  4. Update the Python post-processing if needed (around line 5200)
  5. Document it in the reference guide

Example for a hypothetical IFLA_NEW_FEATURE (65):

// In C_SOURCE - Add to IFLA_ATTR_NAMES
[65] = "IFLA_NEW_FEATURE",

// In parse_ifla_attributes() - Add decode case
case 65:  // IFLA_NEW_FEATURE
    if (rta_len >= sizeof(uint32_t)) {
        uint32_t value = *(uint32_t*)RTA_DATA(rta);
        append_comma(info_json);
        append_to_buffer(info_json, "\"new_feature\": %u", value);
    }
    break;

Adding New Interface Types

To support a new interface kind (e.g., "newtype"):

  1. Add kind detection in IFLA_LINKINFO parsing (around line 2000)
  2. Create a type-specific attribute parser
  3. Add Python-side processing if needed
  4. Update output formatters

Debugging New Features

Enable verbose debugging during development:

# Add debug output in C code (temporary)
fprintf(stderr, "DEBUG: Processing attribute type %d, len %d\n", 
        rta_type, rta_len);

# Or use Python logging
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.debug(f"Interface: {if_name}, Data: {data}")

Code Organization Best Practices

⚠️ Important Guidelines:
  • Keep C and Python synchronized: Struct definitions must match between C code and CFFI cdef
  • Handle padding: Use __attribute__((packed)) for structs read directly from kernel
  • Version guards: Check kernel version before using newer attributes
  • Error handling: Always check return values from C functions
  • Memory safety: Free allocated memory before returning from C functions

Testing Strategy

Unit Testing

Create test scenarios for different interface configurations:

#!/bin/bash
# test_script.sh - Comprehensive testing

# Test 1: Basic execution
echo "Test 1: Basic execution"
sudo python3 device_info.py > /tmp/test1.json || exit 1

# Test 2: Validate JSON
echo "Test 2: JSON validation"
jq empty /tmp/test1.json || exit 1

# Test 3: Check for required fields
echo "Test 3: Required fields"
jq -e '.lo.ifname == "lo"' /tmp/test1.json || exit 1

# Test 4: All output modes
for mode in "--extended" "--addresses" "--summary"; do
    echo "Test 4: Mode $mode"
    sudo python3 device_info.py $mode > /dev/null || exit 1
done

echo "All tests passed!"

Integration Testing

Test with various interface configurations:

# Create test VLAN
sudo ip link add link eth0 name eth0.100 type vlan id 100
sudo python3 device_info.py | jq '.["eth0.100"]'
sudo ip link del eth0.100

# Create test bridge
sudo ip link add br0 type bridge
sudo python3 device_info.py --summary | grep br0
sudo ip link del br0

# Create veth pair
sudo ip link add veth0 type veth peer name veth1
sudo python3 device_info.py | jq '.veth0.veth'
sudo ip link del veth0

Performance Monitoring

Track execution time and resource usage:

# Time the execution
$ time sudo python3 device_info.py > /dev/null

# Monitor memory usage
$ /usr/bin/time -v sudo python3 device_info.py > /dev/null 2>&1 | \
  grep -E "(Maximum resident set size|User time|System time)"

# Profile the script
$ sudo python3 -m cProfile -o profile.stats device_info.py
$ python3 -c "import pstats; p = pstats.Stats('profile.stats'); p.sort_stats('cumulative').print_stats(20)"

Documentation Updates

When modifying the tool, update:

🔍 Troubleshooting

Common Issues and Solutions

Issue: Permission Denied

Error: OSError: [Errno 13] Permission denied

Solution: The script requires root access to create Netlink sockets:

$ sudo python3 device_info.py

Or add CAP_NET_ADMIN capability:

$ sudo setcap cap_net_admin+ep $(which python3)
$ python3 device_info.py  # No sudo needed

Issue: CFFI Import Error

Error: ModuleNotFoundError: No module named 'cffi'

Solution: Install CFFI:

$ pip install cffi
# Or system-wide
$ sudo pip3 install cffi

Issue: Python 3.12+ Setuptools Error

Error: RuntimeError: Python 3.12+ requires setuptools for CFFI

Solution: Install setuptools:

$ pip install setuptools

Issue: Old Python Version

Error: RuntimeError: Python 3.8 or higher is required

Solution: Upgrade Python or use a virtual environment:

# Check your Python version
$ python3 --version

# Use a newer Python if available
$ python3.10 device_info.py

# Or install a newer Python version
$ sudo apt-get install python3.10  # Debian/Ubuntu
$ sudo yum install python310       # RHEL/CentOS

Issue: Compilation Errors

Error: CompileError: command 'gcc' failed

Solution: Install build essentials and kernel headers:

# Debian/Ubuntu
$ sudo apt-get install build-essential linux-headers-$(uname -r)

# RHEL/CentOS
$ sudo yum groupinstall "Development Tools"
$ sudo yum install kernel-devel

# Verify gcc is installed
$ gcc --version

Issue: Empty or Incomplete Output

Possible causes and solutions:

# Check for kernel version requirements
$ uname -r
$ grep -A 5 "IFLA_.*Min Kernel" IFLA_IFA_REFERENCE.md

# Run in specific namespace
$ sudo ip netns exec myns python3 device_info.py

Issue: WireGuard Information Not Showing

Checklist:

  1. Verify WireGuard module is loaded: lsmod | grep wireguard
  2. Check if WireGuard interfaces exist: wg show
  3. Ensure Generic Netlink family is registered: genl-ctrl-list | grep wireguard
  4. Use --wireguard flag to isolate WireGuard output
# Load WireGuard module
$ sudo modprobe wireguard

# Create test interface
$ sudo ip link add dev wg0 type wireguard

# Run script
$ sudo python3 device_info.py --wireguard

Issue: Unknown Attributes Appearing

If you see unknown_attrs in the output, it means the kernel is providing attributes that aren't decoded by the script.

Investigation steps:

  1. Note the attribute numbers
  2. Check /usr/include/linux/if_link.h for the constant definition
  3. Add the attribute to IFLA_ATTR_NAMES in the C code
  4. Implement proper decoding
# Find attribute definition
$ grep "IFLA_.*=" /usr/include/linux/if_link.h | grep -E "\s+$(unknown_attr_num)\b"

Issue: CFFI Struct Padding Errors

If you encounter alignment or padding issues with C structs:

Solution: Add __attribute__((packed)) to struct definitions, especially for:
  • Structs read directly from kernel buffers
  • Netlink message headers
  • Attribute structures
// Correct struct definition
typedef struct __attribute__((packed)) {
    uint16_t rta_len;
    uint16_t rta_type;
} rtattr_t;

Debugging Techniques

Enable Verbose Output

Modify the C code temporarily to add debug prints:

// Add at the beginning of problematic function
#define DEBUG 1
#ifdef DEBUG
fprintf(stderr, "DEBUG: Entering function with param=%d\n", param);
#endif

Capture Raw Netlink Messages

Use strace to see raw Netlink communication:

$ sudo strace -e trace=sendto,recvfrom python3 device_info.py 2>&1 | \
  grep -A 5 "sendto.*netlink"

Compare with ip Command

Verify output against standard tools:

# Compare interface list
$ ip -j link show | jq -r '.[].ifname' | sort > /tmp/ip_output.txt
$ sudo python3 device_info.py | jq -r 'keys[]' | sort > /tmp/script_output.txt
$ diff /tmp/ip_output.txt /tmp/script_output.txt

# Compare addresses
$ ip -j addr show dev eth0 | jq '.[] | .addr_info'
$ sudo python3 device_info.py | jq '.eth0.addresses'

Getting Help

If you encounter issues not covered here:

  1. Check kernel logs: sudo dmesg | tail -50
  2. Verify system requirements are met
  3. Test with minimal configuration (only loopback interface)
  4. Check for conflicting network management tools
  5. Review recent kernel or distribution updates

📚 API Reference

Complete reference for IFLA and IFA constants used in Linux RTNetlink.

IFLA Constants (Interface Link Attributes)

These constants are defined in <linux/if_link.h> and used for querying/configuring network interface properties.

Basic Interface Properties (0-10)

Constant Value Description
IFLA_UNSPEC 0 Unspecified/invalid attribute
IFLA_ADDRESS 1 Hardware (MAC) address
IFLA_BROADCAST 2 Hardware broadcast address
IFLA_IFNAME 3 Interface name (string)
IFLA_MTU 4 Maximum Transmission Unit
IFLA_LINK 5 Link to parent device (for VLANs, etc.)
IFLA_QDISC 6 Queueing discipline name
IFLA_STATS 7 Interface statistics (legacy, 32-bit)
IFLA_MASTER 10 Master device for bonding/bridging

Operational State and Configuration (11-20)

Constant Value Description
IFLA_TXQLEN 13 Transmit queue length
IFLA_OPERSTATE 16 Operational state (up/down/dormant)
IFLA_LINKMODE 17 Link mode (default/dormant)
IFLA_LINKINFO 18 Link type specific info (nested)
IFLA_IFALIAS 20 Interface alias (description)

Statistics and Monitoring (21-35)

Constant Value Description
IFLA_STATS64 23 Interface statistics (64-bit, preferred)
IFLA_AF_SPEC 26 Address family specific attributes
IFLA_PROMISCUITY 30 Promiscuity count
IFLA_CARRIER 33 Physical carrier status
IFLA_CARRIER_CHANGES 35 Number of carrier changes

Hardware Offload Properties (40-43)

Constant Value Description
IFLA_GSO_MAX_SEGS 40 GSO max segments
IFLA_GSO_MAX_SIZE 41 Generic Segmentation Offload max size
IFLA_XDP 43 eXpress Data Path (XDP) configuration

Carrier Event Tracking (47-49)

Constant Value Description
IFLA_CARRIER_UP_COUNT 47 Carrier up event count
IFLA_CARRIER_DOWN_COUNT 48 Carrier down event count
IFLA_NEW_IFINDEX 49 New interface index

Recent Additions (52-64) - Kernel 5.0+

Constant Value Min Kernel Description
IFLA_ALT_IFNAME 53 5.5 Alternative interface names
IFLA_PERM_ADDRESS 54 5.6 Permanent hardware address
IFLA_PARENT_DEV_NAME 56 5.10 Parent device name
IFLA_GRO_MAX_SIZE 58 5.15 GRO max size
IFLA_TSO_MAX_SIZE 59 5.18 TSO max size
IFLA_TSO_MAX_SEGS 60 5.18 TSO max segments
IFLA_GSO_IPV4_MAX_SIZE 63 6.2 GSO IPv4 max size
IFLA_GRO_IPV4_MAX_SIZE 64 6.2 GRO IPv4 max size

IFA Constants (Interface Address Attributes)

These constants are defined in <linux/if_addr.h> and used for querying/configuring IP addresses.

Basic Address Properties (0-8)

Constant Value Description
IFA_UNSPEC 0 Unspecified/invalid attribute
IFA_ADDRESS 1 Interface address (IPv4/IPv6)
IFA_LOCAL 2 Local address (for point-to-point)
IFA_LABEL 3 Address label/alias
IFA_BROADCAST 4 Broadcast address (IPv4 only)
IFA_ANYCAST 5 Anycast address (IPv6 only)
IFA_CACHEINFO 6 Address lifetime information
IFA_FLAGS 8 Extended address flags (32-bit)

Recent Additions (9-11) - Kernel 4.20+

Constant Value Min Kernel Description
IFA_RT_PRIORITY 9 4.20 Route priority for this address
IFA_TARGET_NETNSID 10 5.0 Target network namespace ID
IFA_PROTO 11 5.1 Address protocol (how configured)

Address Flags (IFA_F_*)

These are flag bits used within the IFA_FLAGS attribute:

Flag Hex Value Description
IFA_F_SECONDARY 0x01 Secondary/alias address (IPv4)
IFA_F_TEMPORARY 0x01 Temporary address (IPv6 privacy)
IFA_F_NODAD 0x02 Skip Duplicate Address Detection
IFA_F_OPTIMISTIC 0x04 Optimistic DAD (usable immediately)
IFA_F_DADFAILED 0x08 DAD failed
IFA_F_DEPRECATED 0x20 Deprecated address
IFA_F_TENTATIVE 0x40 Tentative (DAD in progress)
IFA_F_PERMANENT 0x80 Permanent address
IFA_F_MANAGETEMPADDR 0x100 Manage temporary addresses
IFA_F_NOPREFIXROUTE 0x200 Don't create prefix route
IFA_F_STABLE_PRIVACY 0x800 Stable privacy address

Address Readiness States

The tool computes an address "readiness" state based on interface state and address flags:

State Symbol Condition Meaning
ready Interface UP, no DAD flags Address is fully operational
pending TENTATIVE or OPTIMISTIC flag, or link DORMANT Configuration in progress
failed DADFAILED flag set Duplicate address detected
down Interface DOWN or LOWERLAYERDOWN Interface not operational

Operational States (IF_OPER_*)

Value Name Description
0 UNKNOWN Operational state unknown
1 NOTPRESENT Interface not present
2 DOWN Interface is down
3 LOWERLAYERDOWN Lower layer is down
4 TESTING Interface in testing mode
5 DORMANT Interface dormant
6 UP Interface is up

Bridge STP States

Value Name Description
0 DISABLED STP disabled
1 LISTENING Port is listening
2 LEARNING Port is learning
3 FORWARDING Port is forwarding
4 BLOCKING Port is blocking
📖 Full Reference:
For complete details on all 64+ IFLA and 11+ IFA constants, including kernel version compatibility and usage examples, refer to the included IFLA_IFA_REFERENCE.md document.

💡 Advanced Examples

Scripting and Automation

Monitor for New Interfaces

#!/bin/bash
# Watch for interface additions/removals

LAST_COUNT=0

while true; do
    CURRENT_COUNT=$(sudo python3 device_info.py | jq 'length')
    
    if [ "$CURRENT_COUNT" -ne "$LAST_COUNT" ]; then
        echo "$(date): Interface count changed: $LAST_COUNT → $CURRENT_COUNT"
        sudo python3 device_info.py --summary
        LAST_COUNT=$CURRENT_COUNT
    fi
    
    sleep 2
done

Alert on Carrier Loss

#!/bin/bash
# Alert when critical interfaces lose carrier

CRITICAL_IFACES="eth0 eth1"

for iface in $CRITICAL_IFACES; do
    CARRIER=$(sudo python3 device_info.py | \
             jq -r ".\"$iface\".carrier // false")
    
    if [ "$CARRIER" = "false" ]; then
        echo "ALERT: $iface has no carrier!"
        # Send notification, email, etc.
    fi
done

Generate Interface Report

#!/bin/bash
# Create comprehensive interface report

REPORT="/tmp/interface_report_$(date +%Y%m%d_%H%M%S).txt"

{
    echo "==================================="
    echo "Interface Report - $(date)"
    echo "==================================="
    echo ""
    
    echo "System Information:"
    echo "  Kernel: $(uname -r)"
    echo "  Hostname: $(hostname)"
    echo ""
    
    echo "Interface Summary:"
    sudo python3 device_info.py --summary
    echo ""
    
    echo "==================================="
    echo "Physical Interfaces:"
    echo "==================================="
    sudo python3 device_info.py | \
        jq -r 'to_entries[] | select(.value.kind == null) | 
               "\(.key): \(.value.operstate) - \(.value.mac_address)"'
    echo ""
    
    echo "==================================="
    echo "Virtual Interfaces:"
    echo "==================================="
    sudo python3 device_info.py | \
        jq -r 'to_entries[] | select(.value.kind != null) | 
               "\(.key): \(.value.kind)"'
    echo ""
    
    echo "==================================="
    echo "WireGuard Interfaces:"
    echo "==================================="
    sudo python3 device_info.py --wireguard
    
} > "$REPORT"

echo "Report saved to: $REPORT"

Integration with Monitoring Systems

Prometheus Exporter Pattern

#!/usr/bin/env python3
# Export metrics in Prometheus format

import subprocess
import json
import sys

def main():
    result = subprocess.run(
        ['sudo', 'python3', 'device_info.py'],
        capture_output=True,
        text=True
    )
    
    if result.returncode != 0:
        sys.exit(1)
    
    interfaces = json.loads(result.stdout)
    
    # Export carrier status
    for name, info in interfaces.items():
        carrier = 1 if info.get('carrier', False) else 0
        print(f'interface_carrier{{interface="{name}"}} {carrier}')
    
    # Export MTU
    for name, info in interfaces.items():
        if 'mtu' in info:
            print(f'interface_mtu{{interface="{name}"}} {info["mtu"]}')
    
    # Export address count
    for name, info in interfaces.items():
        addr_count = len(info.get('addresses', []))
        print(f'interface_addresses{{interface="{name}"}} {addr_count}')

if __name__ == '__main__':
    main()

Nagios/Icinga Check Plugin

#!/bin/bash
# Nagios plugin to check interface status

CRITICAL_IFACES="$1"
WARNING=""
CRITICAL=""

for iface in $CRITICAL_IFACES; do
    DATA=$(sudo python3 device_info.py | jq -r ".\"$iface\"")
    
    if [ "$DATA" = "null" ]; then
        CRITICAL="$CRITICAL Interface $iface not found."
        continue
    fi
    
    OPERSTATE=$(echo "$DATA" | jq -r '.operstate')
    CARRIER=$(echo "$DATA" | jq -r '.carrier // false')
    
    if [ "$OPERSTATE" != "UP" ]; then
        CRITICAL="$CRITICAL $iface is $OPERSTATE."
    elif [ "$CARRIER" = "false" ]; then
        WARNING="$WARNING $iface has no carrier."
    fi
done

if [ -n "$CRITICAL" ]; then
    echo "CRITICAL:$CRITICAL"
    exit 2
elif [ -n "$WARNING" ]; then
    echo "WARNING:$WARNING"
    exit 1
else
    echo "OK: All interfaces operational"
    exit 0
fi

Data Analysis Examples

Find Interfaces with Most Carrier Changes

$ sudo python3 device_info.py | \
  jq -r 'to_entries | 
         map({name: .key, changes: .value.carrier_changes // 0}) | 
         sort_by(.changes) | 
         reverse | 
         .[] | 
         "\(.name): \(.changes) changes"'

List All IPv6 Addresses with DAD State

$ sudo python3 device_info.py | \
  jq -r 'to_entries[] | 
         .key as $iface | 
         .value.addresses[] | 
         select(.family == "ipv6") | 
         "\($iface): \(.address) - \(.readiness)"'

Find All Bridge Ports

$ sudo python3 device_info.py | \
  jq -r 'to_entries[] | 
         select(.value.bridge_port != null) | 
         "\(.key) → \(.value.master) (STP: \(.value.bridge_port.stp_state))"'