Protocol Plugin Development Guide¤
Creating and extending protocol testing capabilities in PANTHER
This guide provides comprehensive instructions for developing protocol plugins that define testing logic and configurations for specific network protocols within the PANTHER framework.
Advanced Development Topic
Protocol plugin development requires deep understanding of both the target protocol and PANTHER's architecture. Consider starting with Service Plugin Development if you're new to PANTHER plugin development.
Overview¤
Protocol plugins enable PANTHER to test different network protocols by defining:
- Test Scenarios: Standard conformance and performance tests
- Configuration Parameters: Protocol-specific settings and options
- Validation Rules: Criteria for determining test success/failure
- Protocol Behavior: Expected interactions and message flows
Development Setup¤
Prerequisites¤
Before creating a protocol plugin, ensure you have:
- PANTHER Development Environment: Complete PANTHER framework installation
- Protocol Specification: Access to protocol RFCs, drafts, or specifications
- Reference Implementation: At least one working implementation for testing
- Test Vector Knowledge: Understanding of expected protocol behaviors
Development Tools¤
# Install development dependencies
pip install -e .[dev]
# Run tests during development
pytest tests/unit/plugins/protocols/
# Validate plugin structure
python -m panther.plugins.plugin_loader --validate protocols
Plugin Architecture¤
Directory Structure¤
Create your protocol plugin following this structure:
plugins/protocols/
├── client_server/ # or peer_to_peer/
│ └── your_protocol/ # Protocol name (e.g., "quic", "http")
│ ├── __init__.py
│ ├── README.md # Protocol-specific documentation
│ ├── config_schema.py # Configuration validation
│ ├── protocol_plugin.py # Main implementation
│ ├── test_scenarios/ # Test scenario definitions
│ │ ├── __init__.py
│ │ ├── conformance.py
│ │ ├── performance.py
│ │ └── interop.py
│ └── versions/ # Protocol version support
│ ├── __init__.py
│ ├── v1_0/
│ └── v2_0/
Base Protocol Interface¤
All protocol plugins must implement the ProtocolInterface
:
# filepath: /panther/plugins/protocols/protocol_interface.py
from abc import ABC, abstractmethod
from panther.plugins.plugin_interface import IPlugin
class ProtocolInterface(IPlugin):
"""Base interface for all protocol plugins."""
@abstractmethod
def get_supported_versions(self) -> list:
"""Return list of supported protocol versions."""
pass
@abstractmethod
def get_test_scenarios(self) -> dict:
"""Return available test scenarios by category."""
pass
@abstractmethod
def validate_configuration(self, config: dict) -> bool:
"""Validate protocol-specific configuration."""
pass
@abstractmethod
def setup_test_environment(self, config: dict):
"""Setup testing environment for this protocol."""
pass
@abstractmethod
def execute_test_scenario(self, scenario: str, config: dict):
"""Execute a specific test scenario."""
pass
Implementation Steps¤
Step 1: Configuration Schema¤
Define your protocol's configuration schema in config_schema.py
:
# filepath: your_protocol/config_schema.py
from dataclasses import dataclass, field
from typing import Dict, List, Optional
from panther.plugins.protocols.config_schema import ProtocolConfig
@dataclass
class YourProtocolConfig(ProtocolConfig):
"""Configuration schema for YourProtocol."""
# Protocol version
version: str = "1.0"
# Protocol-specific parameters
connection_timeout: int = 30
max_packet_size: int = 1500
enable_feature_x: bool = True
# Test configuration
test_scenarios: List[str] = field(default_factory=lambda: ["handshake", "data_transfer"])
validation_rules: List[str] = field(default_factory=lambda: ["conformance"])
# Advanced options
custom_parameters: Dict[str, str] = field(default_factory=dict)
Step 2: Main Plugin Implementation¤
Create your protocol plugin class in protocol_plugin.py
:
# filepath: your_protocol/protocol_plugin.py
from typing import Dict, List
from panther.plugins.protocols.protocol_interface import ProtocolInterface
from .config_schema import YourProtocolConfig
class YourProtocolPlugin(ProtocolInterface):
"""Protocol plugin for YourProtocol testing."""
def __init__(self):
super().__init__()
self.config = None
self.supported_versions = ["1.0", "1.1", "2.0"]
def get_supported_versions(self) -> List[str]:
"""Return supported protocol versions."""
return self.supported_versions
def get_test_scenarios(self) -> Dict[str, List[str]]:
"""Return available test scenarios by category."""
return {
"conformance": [
"handshake",
"data_transfer",
"error_handling",
"connection_close"
],
"performance": [
"throughput",
"latency",
"connection_setup_time"
],
"interoperability": [
"version_negotiation",
"extension_support"
]
}
def validate_configuration(self, config: dict) -> bool:
"""Validate protocol configuration."""
try:
self.config = YourProtocolConfig(**config)
# Add custom validation logic
if self.config.version not in self.supported_versions:
raise ValueError(f"Unsupported version: {self.config.version}")
return True
except Exception as e:
self.logger.error(f"Configuration validation failed: {e}")
return False
def setup_test_environment(self, config: dict):
"""Setup testing environment."""
if not self.validate_configuration(config):
raise ValueError("Invalid configuration")
# Setup protocol-specific environment
self._setup_protocol_handlers()
self._configure_test_parameters()
def execute_test_scenario(self, scenario: str, config: dict):
"""Execute a test scenario."""
if scenario == "handshake":
return self._test_handshake()
elif scenario == "data_transfer":
return self._test_data_transfer()
# ... other scenarios
def _test_handshake(self):
"""Test protocol handshake."""
# Implement handshake testing logic
pass
def _test_data_transfer(self):
"""Test data transfer functionality."""
# Implement data transfer testing logic
pass
Step 3: Test Scenarios¤
Organize test scenarios in separate modules for maintainability:
# filepath: your_protocol/test_scenarios/conformance.py
from typing import Dict, Any
class ConformanceTests:
"""Conformance test scenarios for YourProtocol."""
@staticmethod
def handshake_test(config: Dict[str, Any]) -> Dict[str, Any]:
"""Test protocol handshake conformance."""
return {
"test_name": "handshake_conformance",
"description": "Verify protocol handshake follows specification",
"steps": [
"initiate_connection",
"exchange_parameters",
"verify_handshake_completion"
],
"success_criteria": [
"connection_established",
"parameters_negotiated",
"no_protocol_errors"
]
}
Step 4: Plugin Registration¤
Register your plugin in __init__.py
:
# filepath: your_protocol/__init__.py
from .protocol_plugin import YourProtocolPlugin
__all__ = ["YourProtocolPlugin"]
# Plugin metadata
PLUGIN_NAME = "your_protocol"
PLUGIN_VERSION = "1.0.0"
PLUGIN_DESCRIPTION = "YourProtocol testing plugin"
PLUGIN_CLASS = YourProtocolPlugin
Testing Your Plugin¤
Unit Tests¤
Create comprehensive unit tests for your plugin:
# filepath: tests/unit/plugins/protocols/test_your_protocol.py
import pytest
from panther.plugins.protocols.your_protocol import YourProtocolPlugin
class TestYourProtocolPlugin:
def setup_method(self):
self.plugin = YourProtocolPlugin()
def test_supported_versions(self):
versions = self.plugin.get_supported_versions()
assert "1.0" in versions
assert len(versions) > 0
def test_configuration_validation(self):
valid_config = {
"version": "1.0",
"connection_timeout": 30
}
assert self.plugin.validate_configuration(valid_config)
invalid_config = {
"version": "invalid_version"
}
assert not self.plugin.validate_configuration(invalid_config)
def test_test_scenarios(self):
scenarios = self.plugin.get_test_scenarios()
assert "conformance" in scenarios
assert "handshake" in scenarios["conformance"]
Integration Tests¤
Test your plugin with the PANTHER framework:
# Test plugin loading
python -c "
from panther.plugins.plugin_loader import PluginLoader
loader = PluginLoader()
plugin = loader.load_plugin('protocols', 'client_server', 'your_protocol')
print('Plugin loaded successfully')
"
# Run integration test
python -m panther --config test_configs/your_protocol_test.yaml --dry-run
Configuration Integration¤
Adding to Experiment Configuration¤
Update experiment configuration to include your protocol:
# filepath: experiment-config/your_protocol_example.yaml
experiment:
name: "YourProtocol Testing"
description: "Conformance and performance testing for YourProtocol"
protocol:
name: "your_protocol"
version: "1.0"
configuration:
connection_timeout: 30
max_packet_size: 1500
test_scenarios: ["handshake", "data_transfer"]
validation_rules: ["conformance", "performance"]
services:
iut: "your_protocol_implementation"
tester: "generic_tester"
environment:
execution: "default"
network: "docker_compose"
Best Practices¤
Code Quality¤
- Follow PEP 8: Use consistent Python coding style
- Type Hints: Add type annotations for better code clarity
- Docstrings: Document all public methods and classes
- Error Handling: Provide meaningful error messages and logging
Protocol Implementation¤
- Specification Compliance: Ensure tests match protocol specifications
- Version Support: Handle multiple protocol versions gracefully
- Extensibility: Design for future protocol extensions
- Performance: Optimize for test execution speed
Testing¤
- Comprehensive Coverage: Test normal and edge cases
- Mock External Dependencies: Use mocks for network interactions
- Reproducible Tests: Ensure tests run consistently
- Documentation: Include test scenario documentation
Common Pitfalls¤
Configuration Issues¤
- Missing Validation: Always validate configuration parameters
- Default Values: Provide sensible defaults for optional parameters
- Type Checking: Ensure parameter types match expectations
Test Implementation¤
- Timeout Handling: Always set appropriate timeouts for network operations
- State Management: Clean up test state between scenarios
- Error Propagation: Properly handle and report test failures
Integration Problems¤
- Plugin Discovery: Ensure proper plugin registration and naming
- Dependency Management: Handle dependencies on other plugins gracefully
- Resource Cleanup: Always clean up resources after tests
Debugging Tips¤
Plugin Loading Issues¤
# Check plugin discovery
python -m panther.plugins.plugin_loader --list protocols
# Validate plugin structure
python -m panther.plugins.plugin_loader --validate protocols your_protocol
Configuration Problems¤
# Test configuration validation in isolation
from your_protocol.config_schema import YourProtocolConfig
try:
config = YourProtocolConfig(**your_config_dict)
print("Configuration valid")
except Exception as e:
print(f"Configuration error: {e}")
Test Execution Issues¤
- Enable Debug Logging: Set logging level to DEBUG
- Use Dry Run Mode: Test configuration without actual execution
- Check Service Logs: Examine IUT and tester service logs
- Network Capture: Use packet capture tools for network-level debugging
Contributing Your Plugin¤
Code Review Checklist¤
Before submitting your plugin:
- All unit tests pass
- Integration tests work with framework
- Documentation is complete and accurate
- Code follows project style guidelines
- Configuration schema is well-defined
- Error handling is comprehensive
Documentation Requirements¤
- Plugin README with usage examples
- Configuration parameter documentation
- Test scenario descriptions
- Integration guide for experiments
- Known limitations and troubleshooting
Submission Process¤
- Fork Repository: Create a fork of the PANTHER repository
- Create Branch: Use descriptive branch name (e.g.,
feature/add-your-protocol
) - Implement Plugin: Follow this development guide
- Add Tests: Include comprehensive test coverage
- Update Documentation: Add plugin to inventory and guides
- Submit PR: Create pull request with detailed description
API Reference¤
For detailed API documentation:
- Protocol Interface: Base interface requirements
- Configuration Schema: Base configuration structure
- Plugin Loader: Plugin discovery and loading
- Test Examples: Example test implementations
Creating a New Protocol Plugin¤
1. Choose Protocol Type¤
Determine whether your protocol follows a client-server or peer-to-peer architecture.
2. Set Up the Plugin Directory¤
Create a directory for your protocol in the appropriate location:
plugins/protocols/<type>/<protocol_name>/
├── __init__.py
├── plugin.py # Main protocol implementation
├── config_schema.py # Configuration schema
├── README.md # Protocol documentation
└── tests/ # Protocol tests
└── test_plugin.py
3. Implement the Protocol Interface¤
Create a class that implements the ProtocolInterface:
# plugins/protocols/<type>/<protocol_name>/plugin.py
from panther.plugins.protocols.protocol_interface import ProtocolInterface
class MyProtocol(ProtocolInterface):
"""My custom protocol implementation."""
def initialize(self, config):
"""Initialize the protocol with configuration."""
self.config = config
# Protocol initialization
def execute(self):
"""Execute the protocol's main functionality."""
# Protocol execution logic
pass
def get_protocol_version(self):
"""Get the version of the protocol."""
return self.config.get("version", "1.0")
def get_protocol_parameters(self):
"""Get the protocol parameters."""
return self.config.get("parameters", {})
def cleanup(self):
"""Clean up resources."""
# Release resources, close connections, etc.
pass
4. Define Configuration Schema¤
Create a schema for your protocol's configuration:
# plugins/protocols/<type>/<protocol_name>/config_schema.py
from panther.core.config.schema import Schema, Optional, And, Or
# Define the configuration schema
schema = Schema({
Optional("version"): str,
Optional("parameters"): {
str: object # Parameter name: parameter value
},
# Protocol-specific parameters
})
5. Register Your Protocol Plugin¤
Make your protocol discoverable by updating your __init__.py
:
# plugins/protocols/<type>/<protocol_name>/__init__.py
from .plugin import MyProtocol
__all__ = ["MyProtocol"]
6. Create Tests¤
Write tests to verify your protocol functions correctly:
# plugins/protocols/<type>/<protocol_name>/tests/test_plugin.py
import pytest
from panther.plugins.protocols.<type>.<protocol_name>.plugin import MyProtocol
def test_protocol_initialization():
protocol = MyProtocol()
config = {"version": "1.0"}
protocol.initialize(config)
assert protocol.get_protocol_version() == "1.0"
def test_protocol_execution():
protocol = MyProtocol()
protocol.initialize({"version": "1.0"})
result = protocol.execute()
# Assert expected behavior
7. Document Your Protocol¤
Create a README.md file using the plugin template that includes:
- Protocol purpose and specifications
- Supported versions and features
- Configuration options
- Usage examples
- Integration with services
- Testing and verification
Best Practices for Protocol Plugins¤
- Version Support: Clearly document which protocol versions are supported
- Error Handling: Provide clear error messages for protocol failures
- Protocol Parameters: Document all configurable protocol parameters
- Interoperability: Test with multiple implementations when possible
- Metrics: Include performance and conformance metrics
Testing Your Protocol¤
Protocol testing should include:
- Unit Tests: Test individual protocol components
- Integration Tests: Test with compatible services
- Conformance Tests: Validate against protocol specifications
- Performance Tests: Measure protocol efficiency
Documentation Verification¤
Ensure all protocol documentation includes source references:
The QUIC protocol supports connection migration.
<!-- src: /panther/plugins/protocols/client_server/quic/__init__.py -->