Skip to content

ADR-SSOT-001: Single Source of Truth (SSOT) for IOCTL Header Files #123

Description

@zarfld

Decision Information

ADR ID: ADR-SSOT-001
Status: ✅ Accepted and Implemented
Date: 2025-12-09
Updated: 2025-12-30 (Implementation Complete)

Context

The IntelAvbFilter codebase suffers from IOCTL definition fragmentation - the same IOCTL codes are defined redundantly across multiple files:

Problem Symptoms:

  • 42 duplicate IOCTL definitions scattered across 8+ files
  • Version skew: Different code values for same IOCTL in different files (e.g., code 39 vs 45)
  • Maintenance burden: Adding a new IOCTL requires changes in 8+ locations
  • Error-prone: Easy to forget updating a file, causing runtime failures
  • No automated detection: Duplicates slip through code review

Root Cause: Lack of architectural enforcement for interface definition centralization.

Affected Components:

  • Driver code (drv/)
  • Unit tests (tests/unit/ioctl/)
  • Integration tests (tests/integration/)
  • Diagnostic tools (tools/)

Decision

We will establish include/avb_ioctl.h as the Single Source of Truth (SSOT) for all IOCTL interface definitions.

Core Principles

  1. One Definition Location: All IOCTL definitions exist ONLY in include/avb_ioctl.h
  2. Include, Never Redefine: All code includes SSOT header instead of defining IOCTLs locally
  3. CI Enforcement: Automated validation rejects code violating SSOT
  4. Portability: SSOT header supports both kernel-mode and user-mode usage

Technical Specification

SSOT Header Location: include/avb_ioctl.h

Required Content:

// ABI Version Tracking
#define AVB_IOCTL_ABI_VERSION 0x00010000u  // v1.0.0

// Kernel/User-Mode Portability
#ifdef _KERNEL_MODE
    // Kernel-mode types (NDIS driver)
    typedef ULONG DWORD;
    typedef ULONG64 UINT64;
#else
    // User-mode types (test tools)
    #include <windows.h>
#endif

// IOCTL Code Generation Macro
#define _NDIS_CONTROL_CODE(request, method) \
    CTL_CODE(FILE_DEVICE_NETWORK, request, method, FILE_ANY_ACCESS)

// IOCTL Definitions (alphabetical order recommended)
#define IOCTL_AVB_INIT_DEVICE           _NDIS_CONTROL_CODE(0x800, METHOD_BUFFERED)
#define IOCTL_AVB_ENUM_ADAPTERS         _NDIS_CONTROL_CODE(0x801, METHOD_BUFFERED)
#define IOCTL_AVB_GET_CLOCK_CONFIG      _NDIS_CONTROL_CODE(0x802, METHOD_BUFFERED)
// ... (30+ total IOCTLs)

Deprecation: external/intel_avb/include/avb_ioctl.h is deprecated. Migration script provided below.

Migration Strategy

Step 1: Create SSOT header if it doesn't exist
Step 2: Identify all files with duplicate IOCTL definitions
Step 3: Remove local definitions, add SSOT include
Step 4: Create CI validation workflow
Step 5: Verify zero duplicates remain

Automated Migration Script (PowerShell):

# migrate-to-ssot.ps1
# Purpose: Migrate IOCTL definitions to SSOT header
# Usage: .\migrate-to-ssot.ps1 -TargetFile <file> -SsotPath "include/avb_ioctl.h"

param(
    [Parameter(Mandatory=$true)]
    [string]$TargetFile,
    
    [Parameter(Mandatory=$false)]
    [string]$SsotPath = "include/avb_ioctl.h"
)

# Step 1: Calculate relative path from target to SSOT
$targetDir = Split-Path $TargetFile -Parent
$relativePath = Resolve-Path -Path $SsotPath -Relative -RelativeBasePath $targetDir

# Step 2: Extract local IOCTL definitions
$content = Get-Content $TargetFile -Raw
$ioctls = [regex]::Matches($content, '(?m)^#define\s+IOCTL_AVB_\w+.*$')

if ($ioctls.Count -eq 0) {
    Write-Host "✅ No IOCTL definitions found in $TargetFile"
    exit 0
}

Write-Host "Found $($ioctls.Count) IOCTL definitions to migrate"

# Step 3: Remove local definitions
foreach ($ioctl in $ioctls) {
    $content = $content -replace [regex]::Escape($ioctl.Value), ""
}

# Step 4: Add SSOT include (if not present)
if ($content -notmatch "#include.*avb_ioctl\.h") {
    $includeStatement = "#include `"$relativePath`"  // SSOT for IOCTL definitions (Implements: #24)`n"
    
    # Insert after last #include
    $lastInclude = [regex]::Match($content, '(?m)^#include.*$')
    if ($lastInclude.Success) {
        $insertPos = $lastInclude.Index + $lastInclude.Length
        $content = $content.Insert($insertPos, "`n$includeStatement")
    } else {
        # Insert at top after header guard
        $content = $includeStatement + $content
    }
}

# Step 5: Write updated file
Set-Content -Path $TargetFile -Value $content -NoNewline

Write-Host "✅ Migrated $TargetFile to use SSOT header"

CI Enforcement Specification

Workflow File: .github/workflows/check-ssot.yml

Validation Steps:

  1. ✅ Verify no duplicate #define IOCTL_AVB_* outside SSOT
  2. ✅ Verify no duplicate _NDIS_CONTROL_CODE macro
  3. ✅ Verify SSOT header exists at include/avb_ioctl.h
  4. ✅ Verify core IOCTLs present (INIT_DEVICE, ENUM_ADAPTERS, GET_CLOCK_CONFIG, GET_HW_STATE)
  5. ⚠️ Warn if shared structures duplicated (non-fatal)

Error Message Template:

❌ Error: Duplicate IOCTL definitions found outside SSOT header!
Found definitions in:
  - include/avb_ioctl.h (SSOT - correct)
  - tests/unit/ioctl/test_file.c (VIOLATION)

All IOCTL definitions must be in include/avb_ioctl.h only.
See Issue #24 (REQ-NF-SSOT-001) and ADR-SSOT-001 (Issue #123).

Consequences

Positive

Eliminates Version Skew: Impossible to have different IOCTL code values
Reduces Maintenance: Changes in 1 location instead of 8+
Improves Reliability: Automated CI catches violations before merge
Better Documentation: Centralized comments and ABI versioning
Portability: Same header works in kernel and user mode
Faster Code Reviews: Single file to review for IOCTL changes
Compiler Enforcement: Include errors if SSOT header missing

Negative

⚠️ Build Dependency: All code depends on single header (acceptable trade-off)
⚠️ CI Build Time: +2 seconds for validation (negligible)
⚠️ Migration Effort: One-time effort to migrate existing code (completed)

Risks Mitigated

RISK-SSOT-001: Developer forgets to update test file → Prevented by CI
RISK-SSOT-002: Version skew causes runtime failures → Prevented by single definition
RISK-SSOT-003: Inconsistent IOCTL codes across components → Prevented by SSOT

Implementation Status

Phase 1: Cleanup (✅ Completed 2025-12-30)

Files Migrated to SSOT:

  1. ✅ tests/unit/ioctl/test_minimal_ioctl.c (removed 4 duplicates)
  2. ✅ tests/unit/ioctl/test_ioctl_trace.c (removed 2 duplicates + custom macro)
  3. ✅ tests/integration/multi_adapter/test_all_adapters.c (removed 3 duplicates)
  4. ✅ tools/check_link_status.c (removed 4 duplicates)
  5. ✅ tools/print_ioctl_codes.c (removed 2 duplicates)
  6. ✅ tools/verify_ioctl_match.c (removed 2 duplicates)

Verification: grep -r "^#define IOCTL_AVB_" --include="*.h" --include="*.c" returns results ONLY from include/avb_ioctl.h

Phase 2: CI Integration (✅ Completed 2025-12-30)

Workflow Created: .github/workflows/check-ssot.yml
Triggers: Push to master/develop, all PRs
Validation Steps: 5 checks (4 fatal, 1 warning)

Phase 3: Testing (✅ Completed 2025-12-30)

Test Issues Created:

Alternatives Considered

Alternative 1: Distributed Definitions (Status Quo)

Rejected: Causes version skew, high maintenance burden, error-prone

Alternative 2: Header Generation from Schema

Considered: Generate avb_ioctl.h from YAML/JSON schema using build script
Rejected: Over-engineering for current needs; SSOT simpler and adequate
Future Option: Could revisit if IOCTL count exceeds 100+

Alternative 3: Per-Component IOCTL Headers

Considered: Separate headers for device management, PTP, diagnostics, etc.
Rejected: Creates artificial boundaries; better to keep all IOCTLs in one place for discoverability

Traceability

Traces to: #24 (REQ-NF-SSOT-001: Single Source of Truth for IOCTL Interface)
Implements Requirements:

  • SSOT-IOCTL-001.1: Single Definition Location ✅
  • SSOT-IOCTL-001.2: Consistent Include Pattern ✅
  • SSOT-IOCTL-001.3: CI Enforcement ✅
  • SSOT-IOCTL-001.4: Kernel/User-Mode Portability ✅
  • SSOT-IOCTL-001.5: ABI Version Tracking ✅

Verified by: #301 (TEST-SSOT-001), #300 (TEST-SSOT-002), #302 (TEST-SSOT-003), #303 (TEST-SSOT-004)

Standards Compliance

  • ISO/IEC/IEEE 12207:2017: Configuration Management (6.3.5)
  • ISO/IEC/IEEE 42010:2011: Architecture Description
  • XP Principles: Simple Design, Collective Code Ownership, Continuous Integration

Review and Approval

Proposed by: Development Team
Reviewed by: Architecture Review Board
Approved by: Project Lead
Status: ✅ ACCEPTED AND IMPLEMENTED

References


Last Updated: 2025-12-30
Implementation Status: ✅ Complete (all 3 phases done)
Next Review: After 6 months or when adding 10+ new IOCTLs

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions