|
PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
|
A C++20 PROFINET IO Controller stack for Linux.
The project provides the building blocks required to discover, configure, connect to, operate and release connections to PROFINET IO-Devices. It is intended as a reusable controller stack rather than as a device-specific application.
The primary focus is protocol correctness, interoperability with real PROFINET devices, deterministic resource management and testability.
The stack currently includes:
Project status: Active development. The main current interoperability objective is reliable, generic AR establishment against real PROFINET IO-Devices, followed by robust cyclic RTC1 communication.
PROFINET IO communication requires considerably more than sending cyclic Ethernet frames.
A controller must first discover or identify a device, establish its communication endpoint, negotiate an Application Relation, provide the expected device configuration, configure cyclic communication, complete parameterization and transition the device into application operation.
The intended lifecycle is broadly:
The goal of this repository is to make this lifecycle available through a C++20 implementation with explicit protocol serialization and clear separation between:
The high-level architecture is:
GSDML configuration feeds the controller configuration used during AR establishment and cyclic I/O setup.
The architecture is evolving toward using Asio for asynchronous I/O and timeout management, while retaining native Linux packet-socket creation and configuration where AF_PACKET functionality is required.
See:
for editable architecture and lifecycle diagrams.
The build defines the ProfinetIoController library and example/test executables. The current CMake configuration builds the core stack from DCP, RPC transport, RPC, RT, cyclic, alarms, blocks, diagnosis, device and GSDML implementations.
The high-level controller front.
ProfinetDevice is intended to provide application-facing operations for:
Typical application code should normally use ProfinetDevice rather than manually coordinating every lower-level component.
Implements PROFINET DCP communication.
Responsibilities include:
DCP operates over Layer 2 Ethernet.
Defines the raw Ethernet transport boundary used by Layer-2 protocol components.
This interface is important because it allows:
The repository also contains mock socket implementations used by protocol and conformance tests.
Defines and implements the transport boundary for PROFINET RPC communication.
The direction of the architecture is to isolate:
This keeps socket and timeout handling separate from RPC packet construction, response parsing and AR state.
Contains PROFINET DCE/RPC and AR connection logic.
Responsibilities include:
This is one of the most important parts of the stack because correct AR establishment is required before cyclic IO communication can operate against real devices.
Defines the connection operations required by higher-level components.
The interface allows device orchestration and lifecycle tests to use mocked RPC behavior rather than requiring real UDP sockets or devices.
Contains PROFINET protocol structures and constants used across the stack.
This includes wire-level structures for major protocol operations.
Network protocol serialization should remain explicit. Correct C++ object layout must never be assumed to imply correct wire layout.
Provides byte-level serialization and parsing helpers.
PROFINET protocol fields are primarily represented in network byte order. This layer centralizes:
Explicit byte serialization is preferred over sending C++ structures with memcpy. This will be updated to C++ 20 std::copy and std::bit_cast.
Implements PROFINET block parsing and serialization.
Responsibilities include parsing and representing block-oriented protocol structures such as:
Parser robustness is particularly important here because block length fields and nested structures must always be validated against the remaining input buffer.
Contains RT_CLASS_1 cyclic communication structures.
Responsibilities include:
IOCR correctness is a primary interoperability concern because incorrect field ordering, offsets or data lengths can cause AR establishment failures.
Implements cyclic RTC1 process-data operation.
Responsibilities include:
The next major development objective after generic AR establishment is reliable operation of this path against real PROFINET hardware.
Implements alarm data structures and parsing.
Supported responsibilities include:
Alarm parsing must remain bounds-checked because notifications may contain nested or variable-length data.
Defines the alarm listener boundary used by higher-level components.
This allows alarm lifecycle behavior to be tested independently from real Layer-2 traffic.
Handles PROFINET alarm reception and acknowledgement.
Responsibilities include:
Implements GSDML parsing.
GSDML is now part of the stack and is used to transform PROFINET device descriptions into C++ configuration data.
The intended configuration flow is:
A key architectural objective is to avoid maintaining separate, manually duplicated descriptions of module identifiers, submodule identifiers and I/O lengths.
Implements diagnosis parsing and interpretation.
Responsibilities include:
Contains standardized PROFINET record indices and lookup helpers.
It provides symbolic access to protocol indices and related metadata rather than spreading raw numeric constants throughout application code.
Defines the project's protocol and transport error hierarchy.
Errors should preserve enough context to identify:
Provides PROFINET vendor ID lookup.
The vendor table is generated rather than manually maintained.
The only remaining Python-related workflow documented by this project is the generation of the PROFINET vendor map.
The generation script reads the authoritative vendor mapping source and produces C++ data for lookup.
For example:
The generated output should be committed when the vendor table is intentionally updated.
Python is not required to build or use the PROFINET IO Controller stack itself.
The repository builds several example applications when PROFINET_BUILD_EXAMPLES is enabled:
pn_discoverpn_set_namepn_read_im0pn_cyclic_demopn_alarm_demopn_diagnosis_demopn_device_demopn_hw_controlThese targets are defined by the current CMake build configuration.
The project uses:
vcpkg.jsonThe current dependency manifest includes:
with Asio pinned through the manifest configuration.
Set VCPKG_ROOT to your vcpkg installation.
For example:
The project uses the vcpkg CMake toolchain through CMakePresets.json.
Do not manually duplicate dependency include paths or library paths when using the supplied presets.
CMakePresets.json is the preferred way to configure the project.
The base preset configures:
The current presets include:
The Linux presets use Ninja and Clang 19, while the coverage preset enables the repository's coverage configuration.
Layer-2 PROFINET operations use Linux raw Ethernet capabilities.
Depending on the configured environment, raw socket operations may require:
The CMake build contains optional setcap support for test executables when ENABLE_SETCAP is enabled and passwordless access to setcap is available.
Avoid running the entire development environment as root when Linux capabilities provide the required access.
The exact returned types and available fields should be taken from the current public header.
ProfinetDevice is intended to provide the high-level application-facing API.
Conceptually:
The public API uses CamelCase naming. New examples and documentation should use the names currently defined in the C++ headers rather than historical snake_case names.
Acyclic communication is performed after the device connection and AR state allow the requested operation.
Conceptually:
For production code, the API, slot, subslot and record index should originate from device configuration or explicit application configuration rather than unexplained literals.
The intended usage model is:
This is preferable to manually duplicating module and submodule identifiers and I/O lengths throughout application code.
The intended cyclic flow is:
or more linear:
Cyclic communication should only start after the AR and required parameterization/application-ready lifecycle have completed successfully.
The repository uses GoogleTest and GoogleMock.
The test target includes coverage across:
The current CMake target lists these tests explicitly.
For PROFINET protocol code:
Important regression validation candidates include:
The repository contains:
This script adds Doxygen-compatible headers to C++ source and header files.
It scans recursively for:
files and adds:
when a compatible file header is not already present.
Usage:
Or target a specific directory:
Use --force to replace an existing compatible @file / @brief header:
The script deliberately avoids silently adding a second header when a file already starts with a different @file declaration.
The diagrams provide:
See:
ARCHITECTURE
The lifecycle sequence covers:
The following table explains the abbreviations and protocol terminology used throughout the project and its implementation.
| Abbreviation / Term | Meaning | Explanation in this project |
|---|---|---|
| AF_PACKET | Linux Address Family, Packet | Linux socket family used for direct Layer-2 Ethernet frame access. Used by the raw Ethernet transport for DCP, RTC1 and RTA traffic. |
| ALARM CR / AlarmCR | Alarm Communication Relation | PROFINET communication relation used for alarm transport between an IO Controller and IO Device. The project establishes an AlarmCRBlockReq during AR setup and uses it for alarm notifications and acknowledgements. |
| API | Application Process Identifier | PROFINET identifier used to associate protocol objects and IO configuration data with an application process. The project currently uses API 0 for the standard application process and carries API values in ExpectedSubmodule and IOCR structures. |
| AR | Application Relation | Logical PROFINET connection between an IO Controller and IO Device. The AR is established using DCE/RPC and contains the configured communication relations such as IOCRs and AlarmCR. |
| ARBlock | Application Relation Block | Block used during AR establishment/release to describe or control an Application Relation. The project handles AR-related request/response blocks through the RPC layer. |
| ARUUID | Application Relation UUID | UUID uniquely identifying an Application Relation. Generated by the controller when establishing a connection to an IO Device. |
| Asio | Asynchronous I/O library | Standalone C++ Asio library used/planned for asynchronous networking and event-driven socket handling. The project is moving toward using Asio for transport integration while retaining Linux-specific raw-socket functionality where required. |
| Acyclic IO | Non-cyclic IO communication | Communication that does not occur at the cyclic RTC interval. Used for configuration, diagnostics, identification and record read/write operations. |
| Acyclic record | Acyclic record data | PROFINET record identified by API, slot, subslot and index. The project exposes operations such as Read, ReadImplicit and Write for record data. |
| AR | Application Relation | The complete logical connection between controller and device, including parameterization and communication relations. |
| C_SDU | Common Service Data Unit | Service-data portion carried by a communication service. In PROFINET RPC terminology this represents application/service data passed through the RPC protocol structures. |
| Cyclic IO | Cyclic Input/Output | Periodic exchange of process data between an IO Controller and IO Device. In this project it is implemented using PROFINET RTC1 Ethernet frames and CyclicController. |
| CR | Communication Relation | Logical communication channel within a PROFINET Application Relation. An AR may contain multiple CRs, for example IOCRs and an AlarmCR. |
| DCP | Discovery and Configuration Protocol | PROFINET Layer-2 protocol used for device discovery and basic configuration. The project uses DCP Identify to discover devices and DCP Set to configure station names and related information. |
| DCE | Distributed Computing Environment | RPC framework/protocol family on which PROFINET's connection-management RPC communication is based. |
| DCE/RPC | Distributed Computing Environment / Remote Procedure Call | RPC protocol used by PROFINET for connection establishment, parameterization, record access and Application Relation management. The project implements the required DCE/RPC structures and transport. |
| DAP | Device Access Point | Special GSDML-defined module representing the device access point. Typically occupies slot 0 and provides the device-level entry point into the IO configuration. |
| DI | Data Interface | Generic term for an interface carrying data. In this project the term is primarily relevant when discussing protocol/data-layout interfaces rather than as a dedicated PROFINET protocol object. |
| EPM | Endpoint Mapper | DCE/RPC Endpoint Mapper. Used to resolve the RPC endpoint/interface information required to communicate with the PROFINET IO Device. The project defines the EPM interface UUID and lookup operations. |
| EtherType | Ethernet Type field | Ethernet header field identifying the payload protocol. PROFINET RT/RTA uses EtherType 0x8892; the project preserves and validates this field in raw Ethernet frames. |
| GSD | General Station Description | Generic term for the device description mechanism used by PROFINET. Modern PROFINET device descriptions are represented using GSDML. |
| GSDML | General Station Description Markup Language | XML-based format used to describe a PROFINET device, including modules, submodules, IO sizes, identities and configuration capabilities. The project contains a native C++ GSDML parser. |
| I&M | Identification & Maintenance | PROFINET identification and maintenance data. The project supports reading I&M records, including I&M0 and additional I&M records where supported by the device. |
| I&M0 | Identification & Maintenance record 0 | Mandatory basic identification record containing device identification information. |
| I&M1 | Identification & Maintenance record 1 | Identification/maintenance record containing tag-function and location information. |
| I&M2 | Identification & Maintenance record 2 | Identification/maintenance record containing installation-date information. |
| I&M3 | Identification & Maintenance record 3 | Identification/maintenance record containing descriptive/free-text information. |
| I&M4 | Identification & Maintenance record 4 | Identification/maintenance record associated with PROFIsafe-related information. |
| I&M5–I&M15 | Identification & Maintenance records 5–15 | Additional/reserved identification and maintenance records. The project models and can probe/read these records where supported. |
| IOD | IO Device | PROFINET IO Device. The term appears in protocol block names such as IODControl, IODConnect and IODRelease. |
| IODConnect | IO Device Connect | DCE/RPC operation used to establish the PROFINET Application Relation and its associated communication relations. |
| IODControl | IO Device Control | PROFINET control operations used during AR lifecycle transitions such as PrmBegin, PrmEnd, ApplicationReady and release. |
| IODRelease | IO Device Release | Operation used to release an established Application Relation. |
| IO | Input/Output | Process input/output data exchanged between the IO Controller and IO Device. |
| IOCR | Input/Output Communication Relation | Communication Relation responsible for cyclic IO data exchange. A typical AR contains an input IOCR and an output IOCR. |
| IOCRBlockReq | IOCR Block Request | PROFINET request block used to configure an IOCR during AR establishment. It contains the IOCR properties, frame ID, timing parameters and IO data object layout. |
| IOCRBlockRes | IOCR Block Response | Response to an IOCRBlockReq. |
| IOCS | Input/Output Consumer Status | Status byte associated with IO data consumed by the receiving side. It indicates whether the consumer considers the associated IO data valid. |
| IOPS | Input/Output Provider Status | Status byte associated with IO data provided by the sending side. The project uses IOPS to determine whether received process data is valid before exposing it to the application. |
| IODataObject | IO Data Object | Description of an individual process-data element inside an IOCR. It identifies its slot/subslot, data length and offsets for process data and IOxS bytes. |
| IOxS | IO Provider/Consumer Status | Generic notation for either IOPS or IOCS. x represents the provider/consumer role. |
| IP | Internet Protocol | Network-layer protocol used by the UDP transport for DCE/RPC and other IP-based communication. |
| IPv4 | Internet Protocol version 4 | IP version used by the project's UDP/RPC communication. |
| MAC | Media Access Control | Ethernet hardware address. The project uses source and destination MAC addresses for DCP, RTC1 and RTA Layer-2 communication. |
| PDU | Protocol Data Unit | A protocol-specific unit of transmitted data. The project uses the term for DCE/RPC, RTA and other protocol payloads. |
| PNIO | PROFINET IO | PROFINET IO protocol/application layer. The project uses PNIO in protocol status/error handling, interface identifiers and RPC structures. |
| PNIO-CM | PROFINET IO Connection Manager | PROFINET connection-management error/diagnostic domain used in PNIO error decoding. |
| PNIORW | PROFINET IO Read/Write | PROFINET IO read/write service domain used when decoding record-access errors. |
| PrmBegin | Parameterization Begin | AR lifecycle operation indicating the beginning of the parameterization phase. |
| PrmEnd | Parameterization End | AR lifecycle operation indicating that parameterization is complete and the controller is moving toward runtime operation. |
| PROFINET | Process Field Network | Industrial Ethernet communication technology standardized and maintained by PROFIBUS & PROFINET International (PI). |
| PROFINET IO | PROFINET Input/Output | PROFINET system architecture for cyclic process data, acyclic records, alarms and device configuration. |
| RTA | Real-Time Acyclic | PROFINET real-time alarm/acyclic communication carried directly over Ethernet Layer 2. The project implements RTA alarm notification and AlarmAck handling. |
| RTA-PDU | Real-Time Acyclic Protocol Data Unit | Protocol data unit carrying PROFINET RTA traffic, particularly alarms, over Ethernet. |
| RTC | Real-Time Cyclic | PROFINET terminology for cyclic real-time communication. |
| RTC1 | Real-Time Cyclic Class 1 | Standard software-based cyclic PROFINET real-time communication. The project uses RTC1 Ethernet frames for cyclic IO. |
| RTC2 | Real-Time Cyclic Class 2 | Higher-performance real-time cyclic communication class with more deterministic timing requirements than RTC1. It is not currently the project's primary cyclic transport. |
| RTC3 | Real-Time Cyclic Class 3 | Isochronous/highly deterministic real-time communication class associated with advanced PROFINET real-time operation. It is outside the current RTC1 implementation scope. |
| RT | Real-Time | Generic abbreviation used throughout the cyclic implementation for PROFINET real-time communication. |
| RT frame | Real-Time frame | Ethernet frame carrying PROFINET cyclic real-time process data. In this project, this normally refers to an RTC1 frame containing IO data and IOxS status bytes. |
| RT_CLASS_1 | Real-Time Class 1 | Software-based PROFINET real-time communication class used by the project's CyclicController. |
| RT_CLASS_2 | Real-Time Class 2 | PROFINET real-time communication class with stronger timing characteristics than RT_CLASS_1. |
| RT_CLASS_3 | Real-Time Class 3 | PROFINET real-time communication class used for highly deterministic/isochronous communication. |
| RPC | Remote Procedure Call | Communication mechanism allowing the controller to invoke PROFINET device services remotely. The project uses DCE/RPC for AR establishment, parameterization and acyclic services. |
| RPCCon | RPC Connection | Project-specific class representing the DCE/RPC connection to a PROFINET IO Device. It manages RPC operations and the AR lifecycle. |
| RPC_PORT | PROFINET RPC UDP port | UDP port 34964 (0x8894) used for PROFINET DCE/RPC communication by the project. |
| RPC_BIND_PORT | RPC local bind port | UDP port 34965 (0x8895) defined for the local RPC bind side. |
| RT_CLASS_1 | Real-Time Class 1 | PROFINET cyclic communication using standard Ethernet networking without the special hardware scheduling requirements of higher real-time classes. |
| SDU | Service Data Unit | Data supplied by a higher protocol/service layer to a lower protocol layer for transmission. C_SDU is used in the DCE/RPC/protocol context. |
| Subslot | PROFINET subslot | Addressable logical IO component inside a slot. A subslot can contain input data, output data, both, or no process data. |
| Slot | PROFINET slot | Logical position in an IO Device's modular configuration. The project models slot/subslot/module/submodule relationships and derives IO configuration from them. |
| ModuleIdentNumber | Module Identification Number | Numeric identifier describing the expected module at a slot. Supplied by GSDML/device configuration and encoded into the ExpectedSubmodule configuration. |
| SubmoduleIdentNumber | Submodule Identification Number | Numeric identifier describing the expected submodule within a slot. |
| ExpectedSubmodule | Expected Submodule configuration | PROFINET configuration structure describing which module/submodule the controller expects at a slot/subslot. Used during AR establishment. |
| ExpectedSubmoduleBlock | Expected Submodule Block | Block sent during parameterization to tell the IO Device which modules and submodules the controller expects to be present. |
| VLAN | Virtual Local Area Network | Ethernet frame tagging mechanism defined by IEEE 802.1Q. The raw Ethernet implementation can receive and process VLAN-tagged PROFINET frames. |
| VID | VLAN Identifier | Identifier contained in an IEEE 802.1Q VLAN tag. |
| PCP | Priority Code Point | IEEE 802.1Q VLAN priority field. Relevant when analysing VLAN-tagged PROFINET Ethernet frames. |
| TPID | Tag Protocol Identifier | Ethernet VLAN tag identifier. Commonly 0x8100 for IEEE 802.1Q VLAN tagging. |
| UUID | Universally Unique Identifier | 128-bit identifier used by DCE/RPC and PROFINET to identify interfaces and Application Relations. |
| EPM UUID | Endpoint Mapper UUID | UUID identifying the DCE/RPC Endpoint Mapper interface. |
| PNIO Device UUID | PROFINET IO Device interface UUID | DCE/RPC interface UUID identifying the PROFINET IO Device service. |
| PNIO Controller UUID | PROFINET IO Controller interface UUID | DCE/RPC interface UUID identifying the PROFINET IO Controller service. |
| USI | User Structure Identifier | Identifier describing the structure/format of diagnostic or alarm data following a diagnosis header. The project uses USI values such as channel diagnosis, extended channel diagnosis and qualified channel diagnosis. |
| Channel Diagnosis | Channel-level diagnostic data | PROFINET diagnosis describing a problem associated with a particular channel. The project identifies this using USI 0x8000. |
| ExtChannelDiagnosis | Extended Channel Diagnosis | Extended channel diagnostic information. The project identifies this using USI 0x8002. |
| QualifiedChannelDiagnosis | Qualified Channel Diagnosis | Qualified form of channel diagnosis. The project identifies this using USI 0x8003. |
| MultipleDiagnosis | Multiple Diagnosis | Diagnostic structure used when multiple diagnosis items are represented. The project identifies this using USI 0x8001. |
| PNIO Error | PROFINET IO error | Four-byte PROFINET status/error representation used by the RPC and record-access implementation. The project decodes PNIO-CM, PNIORW and related error domains. |
| ErrorCode | Error Code | First component of a PNIO error/status representation identifying the broad error source. |
| ErrorDecode | Error Decode | PNIO error field identifying how the remaining error fields should be interpreted. |
| ErrorCode1 | Error Code 1 | First detailed PNIO error-code component. |
| ErrorCode2 | Error Code 2 | Second detailed PNIO error-code component. |
| AlarmAck | Alarm Acknowledgement | PROFINET response acknowledging receipt/handling of an alarm notification. The project's AlarmListener generates and transmits AlarmAck messages. |
| AlarmNotification | Alarm Notification | PROFINET alarm message sent by an IO Device to the IO Controller. The project receives and parses these in AlarmListener. |
| AlarmCR | Alarm Communication Relation | Communication relation used to transport alarms between controller and device. |
| AR release | Application Relation release | Shutdown sequence in which cyclic IO and alarms are stopped and the Application Relation is released. |
| DataStatus | IO Data Status | Status information associated with cyclic IO data, indicating validity and related state information. |
| IOPS status | IO Provider Status | Provider-side validity indication for an IO data object. The project uses it to decide whether received input data may be consumed by the application. |
| IOCS status | IO Consumer Status | Consumer-side status indication associated with an IO data object. |
| Frame ID | Ethernet Frame Identifier | Identifier assigned to a PROFINET IOCR and used to associate cyclic Ethernet frames with the configured communication relation. |
| SendClockFactor | Send Clock Factor | PROFINET cyclic timing parameter defining the base timing relationship for cyclic communication. |
| ReductionRatio | Reduction Ratio | PROFINET cyclic timing parameter controlling how often an IOCR is transmitted relative to the configured send clock. |
| WatchdogFactor | Watchdog Factor | Parameter defining the tolerance for missed cyclic frames before the communication is considered timed out. |
| DataHoldFactor | Data Hold Factor | Parameter controlling how long previously valid process data may be retained following a communication interruption. |
| RTC data | Real-Time Cyclic data | Process data carried by RTC frames. |
| Ethernet | Ethernet LAN technology | Layer-2 networking technology used directly by DCP, RTC1 and RTA in this project. |
| UDP | User Datagram Protocol | Transport-layer protocol used for DCE/RPC and IP-based PROFINET services. |
| TCP | Transmission Control Protocol | General IP transport protocol. It is not the primary transport used by the PROFINET RPC implementation. |
| IP | Internet Protocol | Network-layer protocol used by UDP-based communication. |
| Layer 2 / L2 | OSI Data Link Layer | Ethernet frame layer. DCP, RTC1 and RTA can operate directly at this layer. |
| Layer 3 / L3 | OSI Network Layer | IP networking layer. Used by the UDP/IP transport for RPC-related communication. |
| AF_PACKET | Linux packet socket family | Linux-specific mechanism allowing applications to send and receive Ethernet frames without going through normal TCP/IP sockets. |
| CI | Continuous Integration | Automated build, test, static-analysis and coverage workflows used by the repository. |
| ASan | AddressSanitizer | Runtime instrumentation used to detect memory errors such as buffer overflows and use-after-free. |
| UBSan | UndefinedBehaviorSanitizer | Runtime instrumentation used to detect undefined C++ behaviour. |
| TSan | ThreadSanitizer | Runtime instrumentation used to detect data races and other threading errors. |
| CMakePresets | CMake Presets | Standardized CMake configuration mechanism used by the project to provide reproducible build configurations. |
| vcpkg | Microsoft C++ package manager | Dependency manager used by the project for third-party C++ dependencies. |
| XML | Extensible Markup Language | Markup language used by GSDML device description files. |
| Doxygen | Documentation generator | Tool used to generate API documentation from the project's C++/Doxygen comments. |
| CLI | Command-Line Interface | Command-line application interface. A project-specific CLI suitable for device discovery/configuration/control is currently under development. |
| RAII | Resource Acquisition Is Initialization | C++ resource-management idiom used throughout the project for sockets, threads and other owned resources. |
| PDU | Protocol Data Unit | Encapsulated unit of data belonging to a particular protocol layer. Used throughout the RPC, alarm and real-time protocol implementations. |
| SDU | Service Data Unit | Data passed between adjacent protocol layers before protocol-specific encapsulation. |
| L2 | Layer 2 | OSI Data Link Layer, corresponding to Ethernet framing in this project. |
| L3 | Layer 3 | OSI Network Layer, corresponding to IP communication. |
| I/O | Input/Output | Generic term for process data flowing between controller and device. |
| HW | Hardware | Used in names such as hardware-check/cyclic test tools for tests requiring a physical PROFINET device. |
| SW | Software | Generic abbreviation used when distinguishing software behaviour from hardware behaviour. |
| TX | Transmit | Direction in which the controller sends a frame or packet. The cyclic controller contains a TX path for output frames. |
| RX | Receive | Direction in which the controller receives a frame or packet. The cyclic controller contains an RX path for input frames. |
| Src MAC | Source MAC Address | Ethernet address of the frame sender. |
| Dst MAC | Destination MAC Address | Ethernet address of the intended Ethernet frame recipient. |
| MTU | Maximum Transmission Unit | Maximum payload size supported by a network interface without fragmentation at the relevant layer. Relevant when constructing Ethernet/IP frames. |
| NIC | Network Interface Controller | Network interface used by the controller to transmit/receive PROFINET Ethernet frames. |
| FD | File Descriptor | Linux integer handle representing an open socket or other kernel resource. The networking implementation uses socket FDs and is planned to integrate them with Asio descriptors. |
| I&M | Identification & Maintenance | PROFINET device identification and maintenance records. |
| RPC activity UUID | RPC Activity Universally Unique Identifier | UUID identifying an RPC activity/request context. Used in DCE/RPC request/response processing. |
| Session Key | RPC session key | PROFINET RPC connection/session value associated with the established Application Relation. |
| XID | Transaction Identifier | Identifier used to correlate DCP requests and responses. The DCP implementation uses transaction/request identifiers when filtering received frames. |
| API | Application Process Identifier | PROFINET application-process identifier used when addressing configuration and record data. |
| Slot/Subslot | PROFINET address | Combined logical address identifying a module/submodule within an IO Device. |
| IOCR reference | IOCR identifier/reference | Controller-selected reference identifying an IOCR within the Application Relation. |
| IOCR type | IOCR direction/type | Identifies whether an IOCR carries input or output process data. |
| Input CR | Input Communication Relation | IOCR carrying data from the IO Device to the IO Controller. |
| Output CR | Output Communication Relation | IOCR carrying data from the IO Controller to the IO Device. |
| DAP | Device Access Point | Device-level module normally associated with slot 0. |
| NO_IO | No Input/Output | Project terminology for a submodule that does not carry process input or output data. Such submodules still participate in expected configuration but do not contribute cyclic process data. |
| I/O Data Description | IO data description | Structure describing the length and status information associated with a submodule's process data. |
| Record Index | Record data index | 16-bit identifier selecting a particular acyclic record associated with a slot/subslot. |
| ReadImplicit | Implicit record read | Project API for reading a record using the implicit addressing/context defined by the PROFINET service. |
| PNRD | PROFINET Record Data | Project terminology/type used for PROFINET record-data responses exchanged through RPC. |
| CM | Connection Manager | Connection-management part of PROFINET IO, particularly visible in PNIO-CM error/status handling. |
| RMPM | RPC/PROFINET parameter-management error domain | Error-code grouping used by the project for connection/parameter-management failures such as missing IOCR blocks or incorrect AlarmCR configuration. |
| EPM Lookup | Endpoint Mapper Lookup | DCE/RPC operation used to resolve the endpoint associated with a requested interface. |
| RT timeout | Real-Time timeout | Condition in which expected cyclic real-time frames are not received within the configured watchdog tolerance. |
| IO watchdog | IO communication watchdog | Cyclic communication supervision mechanism detecting missing or stale RTC frames. |
| Wire format | On-the-wire representation | Exact byte-level representation transmitted over Ethernet/IP. The project contains wire-format regression tests for protocol structures and captured device traffic. |
| Wire-format regression test | Exact protocol serialization regression test | Test verifying that serialization/parsing remains compatible with previously validated packet representations or device captures. |
| DCP Identify | DCP Identify request/response | Layer-2 discovery mechanism used by the controller to find PROFINET devices. |
| DCP Set | DCP Set request/response | Layer-2 configuration operation used to set device properties such as station name. |
| RTC1 frame | Real-Time Cyclic Class 1 Ethernet frame | Ethernet frame containing cyclic process data exchanged at the configured cycle time. |
| RTA frame | Real-Time Acyclic Ethernet frame | Ethernet frame carrying PROFINET alarm/acyclic real-time information. |
| Alarm Data | Alarm payload | Application-specific data contained inside a PROFINET alarm notification. |
| Alarm Type | Alarm classification | PROFINET value identifying the type/category of an alarm. |
| Alarm Priority | Alarm priority | Priority associated with a PROFINET alarm and its communication relation. |
| Local Alarm Reference | Controller-side alarm reference | Reference used by the controller to identify its local AlarmCR endpoint. |
| MaxAlarmDataLength | Maximum Alarm Data Length | Maximum alarm payload size negotiated/configured for the AlarmCR. |
| RT Timeout Factor | Real-Time Timeout Factor | AlarmCR/real-time supervision parameter controlling timeout behaviour. |
| GSDML Module | GSDML-described module | Configurable device module defined in a GSDML file. |
| GSDML Submodule | GSDML-described submodule | Configurable device submodule defined in a GSDML file, including its IO data properties. |
| IO layout | Cyclic IO memory/frame layout | Calculated arrangement of process data, IOPS and IOCS bytes inside an IOCR frame. The project is working toward making one resolved IO layout authoritative for RPC configuration and runtime cyclic IO. |
| IOPS offset | IO Provider Status offset | Byte offset where an IODataObject's IOPS status is placed in the cyclic frame. |
| IOCS offset | IO Consumer Status offset | Byte offset where an IODataObject's IOCS status is placed in the cyclic frame. |
| Frame offset | IO data frame offset | Byte position of an IODataObject's process data within the cyclic Ethernet frame. |
| AR lifecycle | Application Relation lifecycle | Sequence of establishing, parameterizing, activating, operating and releasing an AR. |
| ApplicationReady | Application Ready | AR lifecycle transition indicating that the controller has completed parameterization and is ready for cyclic IO operation. |
| Prm | Parameterization | Abbreviation used in protocol block names such as PrmBegin and PrmEnd. |
| Req | Request | Suffix used for request protocol blocks, e.g. IOCRBlockReq. |
| Res | Response | Suffix used for response protocol blocks, e.g. IOCRBlockRes. |
| CR block | Communication Relation block | Protocol block configuring a particular Communication Relation during AR establishment. |
| BlockReq | Block Request | Protocol structure sent by the controller to request/configure a particular PROFINET service or relation. |
| BlockRes | Block Response | Protocol structure returned by the device in response to a block request. |
| UDP/IP | User Datagram Protocol over Internet Protocol | Network stack used for IP-based PROFINET RPC communication. |
| L2 Ethernet | Layer-2 Ethernet | Direct Ethernet communication without IP. Used by DCP and RTC/RTA traffic. |
| Endpoint | RPC communication endpoint | Network endpoint resolved/used by DCE/RPC to reach a specific PROFINET service. |
| Controller | IO Controller | PROFINET station responsible for configuring an IO Device and exchanging cyclic process data. This project implements the controller side. |
| IO Device / IO-Device | Input/Output Device | PROFINET station that provides/consumes process data and exposes configuration, diagnostic and acyclic services. |
| Provider | IO data provider | Station providing a particular IO data object. Its validity is represented by IOPS. |
| Consumer | IO data consumer | Station consuming a particular IO data object. Its status is represented by IOCS. |
| RTC cycle | Real-Time Cyclic cycle | Repeating time interval at which cyclic IO frames are transmitted and received. |
| Cycle counter | Cyclic sequence counter | Counter used by cyclic IO processing to detect duplicate, stale or out-of-order frames. |
| RT class | Real-Time class | PROFINET classification describing the real-time communication mechanism and timing requirements. |
| IRawEthernetSocket | Raw Ethernet socket interface | Project abstraction around Layer-2 Ethernet transmission/reception, allowing protocol components to be tested independently of the Linux socket implementation. |
| RpcTransport | RPC transport abstraction | Project abstraction separating DCE/RPC protocol handling from the underlying UDP transport. |
| RAII | Resource Acquisition Is Initialization | C++ ownership pattern used for deterministic resource lifetime, including sockets and threads. |
| CI | Continuous Integration | Automated build/test pipeline used to validate changes. |
| CLI | Command-Line Interface | Planned user-facing command-line interface for discovery and device operations. |
| XML | Extensible Markup Language | Underlying markup format of GSDML files. |
| POSIX | Portable Operating System Interface | Operating-system API family used by the Linux networking implementation, including socket/file-descriptor functionality. |
| Linux | Linux operating system | Current target operating system for the native raw-Ethernet and networking implementation. |
| ISO | International Organization for Standardization | Standards organization referenced by the broader industrial communication standards context. |
| IEC | International Electrotechnical Commission | Standards organization responsible for relevant international electrotechnical standards, including the IEC 61158 family covering fieldbus/industrial communication technologies. |
| PI | PROFIBUS & PROFINET International | Organization responsible for the PROFINET technology ecosystem, specifications, profiles and certification framework. |
| IEC 61158 | IEC Industrial Communication Networks standard family | International standards family containing specifications relevant to PROFINET and related industrial communication technologies. |
| IEEE | Institute of Electrical and Electronics Engineers | Standards organization responsible for Ethernet and VLAN standards used by the underlying network. |
| IEEE 802.1Q | IEEE VLAN standard | Ethernet VLAN tagging standard relevant to VLAN-tagged PROFINET frames. |
| IRQ | Interrupt Request | Hardware/software interrupt mechanism. Not part of the project's normal PROFINET protocol model, but relevant when discussing network-driver and real-time behaviour. |
| RTT | Round-Trip Time | Time between transmitting a request and receiving its response. Useful for analysing RPC communication and timeout behaviour. |
| Jitter | Timing variation | Variation in actual cyclic frame timing relative to the configured cycle. Important when evaluating RTC1 scheduling. |
| Watchdog | Communication watchdog | Mechanism that detects missing cyclic communication and moves the controller/device state toward a fault condition. |
| TX | Transmit | Sending a network frame. |
| RX | Receive | Receiving a network frame. |
| IOCR DataLength | IOCR cyclic data length | Total data length represented by an IOCR, including the configured process-data/status layout required by the protocol. |
| Data Description | Process-data description | Description of a submodule's input/output data and associated status lengths within an ExpectedSubmodule structure. |
| Module Properties | Module configuration properties | Encoded PROFINET properties describing module/submodule behaviour. |
| Submodule Properties | Submodule configuration properties | Encoded PROFINET properties describing IO direction and related submodule behaviour. |
| NO-IO | No process IO | Submodule configuration with no cyclic input/output process data. |
| Input | Device → Controller process data | Cyclic process data generated by the IO Device and consumed by the IO Controller. |
| Output | Controller → Device process data | Cyclic process data generated by the IO Controller and consumed by the IO Device. |
| Provider Status | IOPS | Status associated with the station providing an IO data object. |
| Consumer Status | IOCS | Status associated with the station consuming an IO data object. |
The project uses a number of compact suffixes and protocol naming conventions:
| Abbreviation | Meaning | Example |
|---|---|---|
| Req | Request | IOCRBlockReq |
| Res | Response | IOCRBlockRes |
| AR | Application Relation | ARBlockReq |
| CR | Communication Relation | AlarmCRBlockReq |
| IOCR | Input/Output Communication Relation | IOCRBlockReq |
| IOD | IO Device | IODControlReqPrmEnd |
| Prm | Parameterization | PrmBegin, PrmEnd |
| App | Application | IODControlReqAppReady |
| RT | Real-Time | RTClass3 |
| RTA | Real-Time Acyclic | RTA alarm PDU |
| IOPS | IO Provider Status | Cyclic input/output status |
| IOCS | IO Consumer Status | Cyclic input/output status |
| PNIO | PROFINET IO | PNIO status/error |
| EPM | Endpoint Mapper | DCE/RPC endpoint lookup |
| RPC | Remote Procedure Call | RPCCon, RpcTransport |
| DCP | Discovery and Configuration Protocol | DCP Identify |
| UUID | Universally Unique Identifier | AR UUID / interface UUID |
| USI | User Structure Identifier | Diagnostic/alarm structure identifier |
| I&M | Identification & Maintenance | I&M0, I&M1, etc. |
| MAC | Media Access Control address | Source/destination Ethernet address |
| UDP | User Datagram Protocol | RPC transport |
| IP | Internet Protocol | UDP/IP transport |
| VLAN | Virtual Local Area Network | Tagged Ethernet frames |
| PDU | Protocol Data Unit | RPC/RTA protocol unit |
| SDU | Service Data Unit | Service-layer data |
| TX | Transmit | Cyclic TX path |
| RX | Receive | Cyclic RX path |
| HW | Hardware | Hardware test utilities |
| CLI | Command-Line Interface | Planned controller CLI |
| CI | Continuous Integration | GitHub Actions |
| GTest | GoogleTest | Unit-test framework |
| GMock | GoogleMock | Mocking framework |
| Asio | Asynchronous I/O library | Planned/common asynchronous transport infrastructure |
| Term | Meaning | Project relevance |
|---|---|---|
| RT_CLASS_1 / RTC1 | Real-Time Class 1 | Primary cyclic IO mechanism currently implemented by CyclicController. |
| RT_CLASS_2 / RTC2 | Real-Time Class 2 | Higher real-time class; not the current primary implementation target. |
| RT_CLASS_3 / RTC3 | Real-Time Class 3 | Highly deterministic/isochronous real-time class. The protocol layer contains support for related control operations, but the current cyclic runtime is focused on RTC1. |
| RT frame | Real-Time Ethernet frame | Frame carrying cyclic process data. |
| RTA frame | Real-Time Acyclic frame | Frame carrying alarms and related real-time acyclic data. |
| Acyclic record | Non-cyclic record service | Used for configuration, diagnostics, I&M and device-specific data. |
| Cyclic IO | Periodic process-data exchange | Implemented using RTC1 frames. |
A few names in the code are project types or identifiers rather than standards abbreviations:
| Name | Meaning |
|---|---|
RPCCon | Project class representing a PROFINET DCE/RPC connection and AR lifecycle. |
RpcTransport | Transport abstraction used by the RPC implementation. |
CyclicController | Runtime component responsible for cyclic RTC1 TX/RX processing. |
CyclicDataBuilder | Component constructing and updating cyclic IO frame data. |
IODataObject | Runtime description of a cyclic IO data object and its frame offsets/status bytes. |
IOCRSetup | Project configuration describing the IOCR/cyclic configuration before connection. |
IOSlot | Project representation of a configured PROFINET slot/subslot and its IO properties. |
GsdmlDevice | Project representation/parser for a GSDML-described device. |
AlarmListener | Background component receiving, parsing and acknowledging PROFINET alarms. |
IRawEthernetSocket | Testable abstraction for raw Layer-2 Ethernet sockets. |
IRPCCon | Interface abstraction for the RPC connection. |
Bytes | Project alias for a byte buffer (std::vector<std::uint8_t>). |
PNIOError | Project exception/type representing a decoded PROFINET IO error. |
PNRTAHeader | Project representation of the PROFINET RTA header. |
PNInM0 … PNInM15 | Project structures representing the corresponding I&M records. |
Highest priority
The primary objective is reliable AR establishment with different real PROFINET IO-Devices.
Focus on:
Success criterion:
A supported device can establish an AR using configuration derived from the device/application configuration without device-specific protocol hacks.
After generic AR establishment is reliable:
Success criterion:
Application output data reaches the device and device input data is received consistently during long-running cyclic operation.
Move blocking and ad-hoc socket handling toward a coherent asynchronous architecture.
Recommended order:
Use:
Move timeout handling toward:
asio::steady_timerAvoid mixing RPC state machines with low-level blocking recv() loops.
Retain Linux AF_PACKET where required, but integrate the descriptor with Asio.
Target model:
The protocol abstraction should remain frame-oriented.
Migrate DCP receive handling to the Asio-backed raw Ethernet transport.
Move alarm receive loops toward Asio-managed descriptor readiness and cancellation.
Migrate cyclic receive handling after DCP and alarm transports are stable.
Do not prematurely replace deterministic cyclic scheduling with an Asio timer.
First measure the existing timing behavior and establish real-device correctness.
Asio timers can be evaluated later if they meet the required timing characteristics.
Strengthen the path:
Goals:
Develop a CLI suitable for operating and diagnosing the stack.
Potential capabilities:
The CLI should exercise the public controller API rather than duplicating protocol logic.
Expand regression coverage for:
Strengthen automated quality gates with:
The repository already contains CMake warning options and Clang-oriented preset configurations; the next step is ensuring these checks consistently protect protocol behavior.
Only after correctness and interoperability are established.
Potential areas:
Correctness takes priority over micro-optimisation.
| Area | Current caveat | Impact | Recommended direction |
|---|---|---|---|
| AR establishment | Generic AR interoperability remains the highest-priority development area | Without a reliable AR, cyclic communication cannot be generally relied upon | Prioritize exact IODConnect, ExpectedSubmodule, IOCR and AlarmCR validation |
| IOCR | IOCR serialization and DataLength semantics are protocol-sensitive | Incorrect values can cause devices to reject AR establishment | Maintain exact byte-level regression validation tests and compare against captures |
| Cyclic RTC1 | Real-device validation remains essential | Loopback/unit success does not prove interoperability | Validate against multiple physical devices and packet captures |
| Raw Ethernet | Layer-2 communication requires Linux capabilities | Deployment requires correct permissions | Use CAP_NET_RAW; avoid unnecessarily running applications as root |
| Linux packet sockets | AF_PACKET remains Linux-specific | Limits portability | Keep Linux-specific code behind meaningful transport boundaries |
| Asio migration | Migration is ongoing/architectural work | Mixing blocking and async models can complicate lifecycle management | Migrate incrementally: RPC, DCP, alarms, cyclic RX |
| Timing | Cyclic timing is sensitive | Generic event-loop timing may not satisfy all cyclic requirements | Measure before replacing dedicated scheduling |
| GSDML | Parsing is implemented, but configuration integration should continue to mature | Incorrect mapping can propagate into AR and IOCR configuration | Establish one configuration source of truth |
| Protocol serialization | Logical field correctness is insufficient | One incorrect byte or length can break interoperability | Prefer explicit serialization and exact regression validation tests |
| Parser robustness | All network input is potentially malformed | Unsafe parsing can cause crashes or invalid state | Validate every offset and length before reading |
| CLI | CLI functionality is under active development | Operational workflows are not yet fully consolidated | Build CLI on top of the public API |
| Device diversity | PROFINET devices may differ in accepted optional behavior | A flow working with one device may not be sufficiently generic | Test against multiple vendors and use captures as evidence |
The stack should continue to follow these principles:
Do not rely on compiler structure layout for network protocols.
Sockets, descriptors, threads, timers and connection resources should have deterministic lifetime.
Prefer std::unique_ptr when ownership is exclusive.
Avoid std::shared_ptr unless shared lifetime is genuinely required.
Interfaces should exist because they provide:
Do not add abstractions merely to increase abstraction.
Prefer:
std::spanstd::string_viewconstexprenum classFor PROFINET:
Every protocol defect should result in a regression test.
Current priority order:
The most important success criterion is not simply that the stack builds or passes isolated unit tests.
The primary measure of success is:
A C++20 application can discover a real PROFINET IO-Device, derive or supply a valid configuration, establish a correct AR, complete parameterization, enter cyclic operation, exchange process data reliably, handle alarms and acyclic operations where configured, and release all resources deterministically.