Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.20)

project(ARIEC61850Cpp
VERSION 0.4.0
VERSION 0.5.0
DESCRIPTION "Incremental C++20 port of the ARIEC61850 protocol stack"
LANGUAGES CXX)

Expand All @@ -19,7 +19,13 @@ add_library(ariec61850_core
src/goose/publisher_runtime.cpp
src/mms/utc_time.cpp
src/mms/data_value.cpp
src/mms/data_codec.cpp)
src/mms/data_codec.cpp
src/sampled_values/pdu_codec.cpp
src/sampled_values/frame_codec.cpp
src/sampled_values/quality.cpp
src/sampled_values/payload_inspector.cpp
src/sampled_values/sample_counter.cpp
src/sampled_values/stream_supervisor.cpp)

add_library(ARIEC61850::core ALIAS ariec61850_core)

Expand Down Expand Up @@ -55,7 +61,7 @@ if(ARIEC61850_BUILD_TESTS)
ariec61850_apply_warnings(ariec61850_core_tests)
add_test(NAME ariec61850_core_tests COMMAND ariec61850_core_tests)

foreach(test_name IN ITEMS mms goose)
foreach(test_name IN ITEMS mms goose sampled_values)
add_executable(ariec61850_${test_name}_tests tests/test_${test_name}.cpp)
target_link_libraries(ariec61850_${test_name}_tests PRIVATE ARIEC61850::core)
target_compile_features(ariec61850_${test_name}_tests PRIVATE cxx_std_20)
Expand Down
95 changes: 51 additions & 44 deletions MIGRATION_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,39 +27,46 @@ interoperability is complete.

### Phase 1B — GOOSE wire codec

- [x] GOOSE PDU model.
- [x] GOOSE PDU BER encoder/decoder.
- [x] GOOSE `numDatSetEntries` consistency validation.
- [x] GOOSE Ethernet/VLAN/process-bus frame encoder/decoder.
- [x] GOOSE C#-compatible byte-for-byte golden vectors.
- [x] GOOSE malformed/truncated-input regression tests.
- [x] GOOSE PDU model and BER codec.
- [x] GOOSE Ethernet/VLAN/process-bus frame codec.
- [x] Dataset-count and malformed-input validation.
- [x] C#-compatible byte-for-byte golden vectors.

### Phase 1C — GOOSE supervision and publisher runtime

- [x] Subscriber TimeAllowedToLive deadline supervision.
- [x] One-shot expiry events and expiration statistics.
- [x] First/retransmission/duplicate classification.
- [x] Sequence gap and sequence regression detection.
- [x] State change, state jump, and state regression detection.
- [x] `stNum` and `sqNum` 32-bit wraparound behavior.
- [x] Expected control-block, dataset, and configuration-revision checks.
- [x] Changed AllData without `stNum` increment detection.
- [x] Publisher session with C#-compatible state/sequence behavior.
- [x] Publisher retransmission runtime with exponential scheduling.
- [x] Schedule reset and `sqNum = 0` on state changes.
- [x] Stable state timestamp across retransmissions.
- [x] Offline encoded-frame output with no raw-network activation.

### Phase 1D — Sampled Values and evidence hardening

- [ ] Sampled Values ASDU model.
- [ ] Sampled Values APDU and Ethernet frame codec.
- [ ] Sampled Values sequence supervision and stream diagnostics.
- [ ] Captured PCAP equivalence tests from real or simulated IED traffic.
- [ ] Decoder fuzzing corpus for BER, GOOSE, and SV.

**Phase 1 status: MMS and GOOSE wire/runtime layers complete; Sampled Values and
capture/fuzz evidence remain.**
- [x] Subscriber TTL, sequence, state, identity, and wraparound supervision.
- [x] Publisher session and exponential retransmission state machine.
- [x] Stable state timestamps and offline encoded-frame output.

### Phase 1D — Sampled Values

- [x] Sampled Values ASDU model.
- [x] Multi-ASDU SAV PDU model.
- [x] Application-tag-0 BER encoder/decoder.
- [x] Exact `noASDU` consistency validation.
- [x] Optional `datSet`, `refrTm`, `smpRate`, and `smpMod` support.
- [x] Sampled Values Ethernet/VLAN/process-bus frame codec (`0x88BA`).
- [x] `smpCnt` policy and configurable-wrap tracker.
- [x] Continuous, normal-wrap, gap, duplicate, out-of-order, and restart classification.
- [x] Stream identity and configuration-revision supervision.
- [x] Aggregate sequence and missing-sample statistics.
- [x] IEC 61850 Sampled Values quality-word helper.
- [x] Vendor-neutral generic `seqOfData` word inspection.
- [x] Trailing-byte preservation for unknown payload shapes.
- [x] C#-derived PDU and complete Ethernet-frame golden vectors.
- [x] Malformed BER, UTC-time, EtherType, and length rejection tests.

### Phase 1E — evidence hardening

- [ ] Captured GOOSE and SV PCAP equivalence tests from real or simulated IED traffic.
- [ ] C# and C++ executable-oracle comparison in one CI job.
- [ ] Sanitizer jobs.
- [ ] BER, GOOSE, and SV decoder fuzzing corpus.
- [ ] Isolated-laboratory GOOSE and SV interoperability.
- [ ] Real-time SV publisher timing-health validation.

**Phase 1 status: MMS, GOOSE, and Sampled Values deterministic core layers complete;
evidence hardening and active-transport validation remain.**

## Phase 2 — engineering file formats

Expand Down Expand Up @@ -104,22 +111,22 @@ capture/fuzz evidence remain.**

## Current acceptance evidence

- [x] GCC C++20 build with warnings as errors.
- [x] Clang C++20 build with warnings as errors.
- [x] Windows MSVC build and CTest through Phase 1B.
- [x] Windows MSVC build and CTest for Phase 1C.
- [x] GCC C++20 build with warnings as errors through Phase 1D.
- [x] Clang C++20 build with warnings as errors through Phase 1D.
- [x] Windows MSVC build and CTest through Phase 1D.
- [x] Full GitHub Actions matrix passed with 5/5 CTest executables.
- [x] MMS C#-derived golden vector.
- [x] GOOSE PDU C#-derived golden vector.
- [x] GOOSE complete Ethernet frame golden vector with VLAN and process-bus header.
- [x] Malformed BER and GOOSE count-mismatch rejection.
- [x] Deterministic subscriber and publisher runtime regression suite.
- [ ] C# and C++ executable oracle comparison in one CI job.
- [ ] Sanitizer jobs and fuzzing.
- [x] GOOSE PDU and Ethernet-frame golden vectors.
- [x] Deterministic GOOSE subscriber/publisher runtime suite.
- [x] Sampled Values PDU and Ethernet-frame golden vectors.
- [x] Sampled Values counter, supervisor, quality, and payload-diagnostics suite.
- [ ] Captured process-bus PCAP equivalence.
- [ ] Fuzzing and sanitizers.
- [ ] Isolated-lab IED interoperability.

## Safety gate

The Phase 1C publisher is an offline state machine that returns encoded bytes. Active
Npcap transmission, MMS write/control, and IED operation remain outside the enabled
runtime surface until timeout, cancellation, disconnect cleanup, PCAP equivalence, and
isolated-lab tests pass.
GOOSE and Sampled Values publisher components return encoded bytes only. Active Npcap
transmission, real-time SV scheduling, MMS write/control, and IED operation remain
outside the enabled runtime surface until PCAP equivalence, timeout/cancellation,
timing, fuzzing, and isolated-laboratory tests pass.
78 changes: 43 additions & 35 deletions PORT_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

## Current milestone

**Phase 1C — GOOSE subscriber supervision and publisher runtime is implemented.**
**Phase 1D — Sampled Values core codec and supervision is implemented and CI-validated.**

The C++ stack now covers the deterministic path from MMS values through a complete
GOOSE Ethernet frame and the state machines immediately above that wire codec.
The C++ stack now covers deterministic MMS data, GOOSE wire/runtime behavior, and the
core Sampled Values path from ASDU/APDU encoding through Ethernet framing and `smpCnt`
supervision.

## Delivered modules

Expand All @@ -16,52 +17,59 @@ GOOSE Ethernet frame and the state machines immediately above that wire codec.
| Classic PCAP reader/writer | Complete |
| IEC 61850 UTC time | Complete |
| MMS Data / AllData codec | Complete |
| GOOSE PDU codec | Complete |
| GOOSE Ethernet frame codec | Complete |
| GOOSE subscriber supervision | Complete |
| GOOSE publisher session/runtime | Complete, offline frame output only |
| Sampled Values | Not started |
| GOOSE PDU and Ethernet frame codecs | Complete |
| GOOSE subscriber and publisher runtime | Complete, offline frame output only |
| Sampled Values ASDU/APDU/frame codec | Complete |
| Sampled Values counter and stream supervision | Complete |
| Sampled Values quality and generic payload inspection | Complete |
| Captured SV PCAP equivalence | Pending |
| Decoder fuzzing | Pending |
| SCL and COMTRADE | Not started |
| TPKT/COTP/ACSE/MMS association | Not started |
| Reporting and control | Not started |
| Simulator and native UI | Not started |

## Phase 1C behavior
## Phase 1D behavior

Subscriber supervision includes:
Sampled Values wire support includes:

- TimeAllowedToLive deadline calculation and one-shot expiry reporting;
- arrival-gap tracking;
- duplicate, retransmission, sequence-gap, sequence-regression, state-change,
state-jump, and state-regression classification;
- `uint32` counter wraparound;
- expected stream identity validation;
- configuration revision change indication; and
- detection of changed AllData while `stNum` remains unchanged.
- application-tag-0 SAV PDU encoding and decoding;
- multi-ASDU sequence handling and exact `noASDU` consistency checks;
- optional dataset reference, reference time, sample rate, and sample mode fields;
- complete Ethernet/VLAN/process-bus frame handling for EtherType `0x88BA`;
- strict rejection of malformed BER, invalid UTC time, wrong EtherType, trailing APDU
data, and impossible process-bus length declarations; and
- C#-derived byte-for-byte APDU and complete Ethernet-frame vectors.

Publisher runtime includes:
Runtime diagnostics include:

- initial publication with configured state and sequence counters;
- state-change publication with `stNum` increment and `sqNum = 0`;
- retransmissions with `sqNum` increment and wraparound;
- exponential min-time to max-time scheduling;
- schedule reset after every state change; and
- a deterministic `poll(now)` API that avoids sleeping threads and timing-flaky tests.
- sample-counter initialization, increment, configurable wrap, continuity, gaps,
duplicates, out-of-order traffic, and trusted restart classification;
- stream identity and configuration-revision checks with statistics;
- IEC 61850 quality-word encoding/decoding; and
- vendor-neutral big-endian 32-bit payload views without inventing channel semantics.

## Validation

- GNU C++ 14.2, Release, warnings as errors: passed.
- Clang 17, Release, warnings as errors: passed.
- Four CTest executables passed under both compilers:
The final Phase 1D branch passed the complete GitHub Actions matrix:

- GNU C++ / Release / warnings as errors: passed;
- Clang / Release / warnings as errors: passed;
- Windows MSVC / Release / `/W4 /WX`: passed; and
- five CTest executables passed on every platform:
- core foundation;
- MMS values;
- GOOSE wire codec; and
- GOOSE subscriber/publisher runtime.
- Windows MSVC verification is performed by GitHub Actions for every stacked PR.
- GOOSE wire codec;
- GOOSE subscriber/publisher runtime; and
- Sampled Values codec and supervision.

The initial MSVC run identified narrowing construction of `optional<uint16_t>` inside
test fixtures. Explicit `uint16_t` values fixed the portability issue without changing
the library API or wire behavior.

## Safety boundary

No network adapter is opened by Phase 1C. The publisher runtime only returns encoded
Ethernet-frame bytes. Npcap transmission, background network threads, active GOOSE
publishing, MMS writes, and IED controls remain disabled until PCAP equivalence and
isolated-lab interoperability are completed.
Sampled Values support currently parses and returns encoded bytes only. No adapter is
opened, and no real-time publisher thread or raw Ethernet transmission is enabled.
PCAP equivalence, sanitizer/fuzz coverage, timing validation, and isolated-laboratory
interoperability remain required before active process-bus transmission.
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,24 @@ interoperability are complete.

### Phase 1C — GOOSE runtime state machines

- Subscriber TTL supervision and one-shot expiry events.
- `stNum`/`sqNum` classification: first, retransmission, duplicate, gap, regression,
state change, state jump, and state regression.
- 32-bit sequence and state wraparound handling.
- Expected control-block, dataset, and configuration-revision identity checks.
- Detection of data changes without a matching `stNum` increment.
- Publisher session matching the C# counter semantics.
- Subscriber TTL and `stNum`/`sqNum` supervision.
- Duplicate, gap, regression, state-change, and wraparound classification.
- Deterministic publisher runtime with exponential retransmission scheduling.
- State timestamps remain stable during retransmission and change only on a state event.
- Offline encoded-frame output without raw-network activation.

The publisher runtime returns encoded frames to its caller. It does not open Npcap,
raw sockets, or a network interface.
### Phase 1D — Sampled Values core

- Sampled Values ASDU and multi-ASDU APDU models.
- Application-tag-0 BER encoder/decoder with strict `noASDU` validation.
- Ethernet/VLAN/process-bus frame codec for EtherType `0x88BA`.
- Optional `datSet`, `refrTm`, `smpRate`, and `smpMod` field handling.
- `smpCnt` continuity, normal-wrap, gap, duplicate, out-of-order, and restart tracking.
- Stream identity and configuration-revision supervision with aggregate statistics.
- IEC 61850 quality-word helper.
- Vendor-neutral raw `seqOfData` 32-bit word inspection with trailing-byte preservation.
- C#-derived byte-for-byte PDU and complete Ethernet-frame golden vectors.

No Phase 1 runtime opens Npcap, raw sockets, or a network interface.

## Build

Expand Down
37 changes: 21 additions & 16 deletions VALIDATION.txt
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
ARIEC61850 C++ Phase 1C validation
ARIEC61850 C++ Phase 1D validation
Date: 2026-08-06

GNU C++ 14.2 / Release / warnings-as-errors:
GNU C++ / Release / warnings-as-errors / GitHub Actions:
Configure: PASS
Build: PASS
CTest: PASS (4/4 test executables)
CTest: PASS (5/5 test executables)

Clang 17 / Release / warnings-as-errors:
Clang / Release / warnings-as-errors / GitHub Actions:
Configure: PASS
Build: PASS
CTest: PASS (4/4 test executables)
CTest: PASS (5/5 test executables)

Windows MSVC / Release / warnings-as-errors / GitHub Actions:
Windows MSVC / Release / W4/WX / GitHub Actions:
Configure: PASS
Build: PASS
CTest: PASS (4/4 test executables)
CTest: PASS (5/5 test executables)

Test executables:
1. ariec61850_core_tests
2. ariec61850_mms_tests
3. ariec61850_goose_tests
4. ariec61850_goose_runtime_tests
5. ariec61850_sampled_values_tests

Phase 1C runtime checks:
- subscriber sequence and state classification
- TTL expiry and one-shot timeout reporting
- expected stream identity rejection
- state and sequence counter wraparound
- publisher C# sequence semantics
- retransmission schedule and state-change reset
- stable state timestamp across retransmissions
- publisher state and sequence wraparound
Phase 1D Sampled Values checks:
- C#-derived SAV PDU byte-for-byte golden vector
- complete VLAN/process-bus Ethernet frame golden vector
- multi-ASDU encode/decode and exact noASDU validation
- malformed outer tag, sequence, UTC time, trailing bytes, EtherType, and length rejection
- smpCnt continuity, wrap, gap, duplicate, out-of-order, and restart tracking
- stream identity/configuration supervision and aggregate statistics
- quality-word round trip
- generic seqOfData word inspection and trailing-byte preservation

MSVC portability correction:
- explicit uint16_t construction for optional sample-rate, sample-mode, and wrap fixtures
- library API and encoded wire bytes unchanged
34 changes: 34 additions & 0 deletions include/ariec61850/sampled_values/asdu.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include "ariec61850/mms/utc_time.hpp"

#include <cstdint>
#include <optional>
#include <string>
#include <vector>

namespace ar::iec61850::sampled_values {

struct SampledValueAsdu final {
std::string sv_id;
std::string data_set_reference;
std::uint16_t sample_count{};
std::uint32_t configuration_revision{1U};
std::optional<mms::Iec61850UtcTime> reference_time;
std::uint8_t sample_synchronization{2U};
std::optional<std::uint16_t> sample_rate;
std::optional<std::uint16_t> sample_mode;
std::vector<std::uint8_t> sample_payload;

friend bool operator==(const SampledValueAsdu&, const SampledValueAsdu&) = default;
};

struct SampledValuesPdu final {
std::vector<SampledValueAsdu> asdus;

friend bool operator==(const SampledValuesPdu&, const SampledValuesPdu&) = default;
};

} // namespace ar::iec61850::sampled_values
Loading
Loading