Skip to content

Add OPC UA PubSub Ethernet (Layer 2) transport (opc.eth://)#3915

Closed
marcschier wants to merge 3 commits into
part14pubsubfrom
part14pubsub-eth-transport
Closed

Add OPC UA PubSub Ethernet (Layer 2) transport (opc.eth://)#3915
marcschier wants to merge 3 commits into
part14pubsubfrom
part14pubsub-eth-transport

Conversation

@marcschier

@marcschier marcschier commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a third OPC UA PubSub transport — Ethernet (Layer 2) — alongside the existing UDP and MQTT transports, implementing the OPC UA Part 14 Ethernet mapping. PubSub NetworkMessages are carried directly inside raw Ethernet II frames (no IP/UDP), identified by the OPC Foundation EtherType 0xB62C, with optional IEEE 802.1Q VLAN tagging. The existing UADP message encoding and message-level PubSub security are reused — only the transport binding is new.

This targets the part14pubsub feature branch (PR #3892).

What's included

New library Libraries/Opc.Ua.PubSub.Eth (net472/net48/netstandard2.1/net8.0/net9.0/net10.0):

  • Transport profile pubsub-eth-uadp (EthProfiles.PubSubEthUadpTransport, defined in the Eth assembly) and address scheme opc.eth://<mac>[?vid=<0-4095>&pcp=<0-7>] (hyphen/colon/bare-hex MAC forms; legacy :vid.pcp suffix accepted).
  • EthEndpointParser, EthernetFrameCodec (Ethernet II + 802.1Q framing, EtherType filter, 60-octet padding), EthernetDatagramTransport (IPubSubTransport + discovery announcements), and EthPubSubTransportFactory.
  • Provider model: injectable IEthernetFrameChannel / IEthernetFrameChannelFactory with four backends:
    • Linux AF_PACKET and macOS BPF via libc P/Invoke — NativeAOT-clean, default.
    • SharpPcap (libpcap / Npcap) for Windows / cross-platform, opt-in via WithPcap(), kept in the same package (compiled net8.0+, isolated with [UnconditionalSuppressMessage]).
    • In-memory loopback for deterministic, privilege-free tests and local diagnostics.
  • Full DI/fluent surface (AddEthTransport(...), WithPcap()) plus a direct-construct fallback; EthTransportOptions (bindable from OpcUa:PubSub:Eth).

Sample, docs, wiring: ConsoleReferencePubSubClient gains an EthUadp profile (--profile eth-uadp); documented in the Transports section of Docs/PubSub.md (linked from README / Profiles / migration docs); UA.slnx and Directory.Packages.props updated.

NativeAOT evaluation

The SharpPcap backend's AOT safety was decided empirically: an AOT smoke test in Opc.Ua.Aot.Tests exercises the SharpPcap path, and the AOT-published binary ran it successfully ("Dynamic code generation is not supported"). SharpPcap therefore runs under NativeAOT, so unconditional suppression is sufficient (no [RequiresDynamicCode] / [RequiresUnreferencedCode]). The net8.0+ gate avoids the transitive PacketDotNet netstandard NU1701.

Review feedback addressed

  • Merged Docs/PubSubEth.md into the Transports section of Docs/PubSub.md.
  • Added <inheritdoc/> / <summary> documentation to the internal frame-channel classes and their members.
  • Moved the Ethernet profile URI constant from Opc.Ua.Core SecurityConstants.Profiles into a dedicated EthProfiles class in the Opc.Ua.PubSub.Eth assembly.

Validation

  • Opc.Ua.PubSub.Eth builds 0-warning on all six TFMs.
  • Opc.Ua.PubSub.Eth.Tests: 51 pass (net10.0) / 50 pass (net48) — parser, codec (VLAN / padding / EtherType filter), transport loopback round-trip incl. discovery, channels, factory, DI + WithPcap wiring.
  • Opc.Ua.Aot.Tests: builds clean, AOT-publishes, and the 3 Ethernet AOT tests pass.
  • Full UA.slnx net10.0 build: 0 errors; the sample builds clean.

Related Issues

Checklist

  • I have signed the CLA and read the CONTRIBUTING doc.
  • I have added tests that prove my fix is effective or that my feature works and increased code coverage.
  • I have added all necessary documentation.
  • I have verified that my changes do not introduce (new) build or analyzer warnings.
  • I ran all tests locally using the UA.slnx solution against at least .net framework and .net 10, and all passed.
  • I fixed all failing and flaky tests in the CI pipelines and all CodeQL warnings.
  • I have addressed all PR feedback received.

Implements the Part 14 Ethernet mapping (profile pubsub-eth-uadp, EtherType 0xB62C, optional 802.1Q VLAN) as a new Opc.Ua.PubSub.Eth library, reusing the existing UADP encoding and message-level security.

Provides an injectable IEthernetFrameChannel provider with native Linux AF_PACKET / macOS BPF backends (AOT-clean), an opt-in SharpPcap backend via WithPcap() in the same package (net8.0+), and an in-memory loopback backend for deterministic tests. Adds DI/fluent AddEthTransport, the EthUadp sample profile, unit + AOT tests, and docs.
Comment thread Docs/PubSubEth.md Outdated
Comment thread Stack/Opc.Ua.Core/Security/Constants/SecurityConstants.cs
- Move the Ethernet transport profile URI constant out of Opc.Ua.Core SecurityConstants into a dedicated EthProfiles class in the Opc.Ua.PubSub.Eth assembly (its own file, next to the transport code).

- Add <inheritdoc/> to all interface-implementing members and <summary> docs to public constructors and internal members of the internal frame-channel classes.

- Merge Docs/PubSubEth.md into the Transports section of Docs/PubSub.md and update the README / Profiles links accordingly.
- ETH-SEC-02: return the send ArrayPool buffer with clearArray:true so plaintext NetworkMessage residue is not exposed in the shared pool.

- ETH-SEC-01: drop the redundant receive-side copy (backends yield a distinct single-use array per frame) to cut GC pressure under a frame flood.

- ETH-SEC-03: hold the channel lock across the AF_PACKET/BPF send syscall to close the file-descriptor-reuse race with concurrent close.

- ETH-SEC-04/05: harden BPF record-parse bounds and EthernetFrameCodec.GetRequiredLength against integer overflow.

- ETH-SEC-06: log a prominent warning when an opc.eth:// connection opens with SecurityMode=None; document the no-transport-security model, least-privilege, loopback-not-a-boundary and supply-chain notes in Docs/PubSub.md.

Adds codec-overflow and unsecured-config-warning tests (Eth tests 54/53 pass, 0-warning).
@marcschier

Copy link
Copy Markdown
Collaborator Author

CI triage (build 14972)

The two red checks are pre-existing macOS hosted-runner flakiness unrelated to this PR, not regressions from the Ethernet transport changes:

  • Tests_Opc_Ua_History_Tests_mac — all 306 History tests passed; the job failed only because the dotnet test process exited with code 1 on teardown. This job is chronically failing on master (e.g. builds 14961 and 14843).
  • Tests_Opc_Ua_PubSub_Tests_macUdpLoopbackActionResponderAnswersRequesterAsync fails with a SocketError sending to the multicast group 224.0.2.14 — a known multicast limitation of the hosted macOS runners, in the core UDP test (not modified by this PR). The macOS runners flake broadly (master 14961 also failed Gds and Core.Diagnostics on mac).

This PR's own jobs are green: Tests_Opc_Ua_PubSub_Eth_Tests passed on both macOS (net10.0) and Windows (net48), and all 84 non-mac-flaky checks passed.

No branch-related fix is required; the failing jobs are environmental and should clear on a runner re-run.

marcschier added a commit that referenced this pull request Jun 29, 2026
Squash-merge of PR #3915 (head part14pubsub-eth-transport) into part14pubsub (#3892).
marcschier added a commit that referenced this pull request Jun 29, 2026
Apply whitespace + style + safe analyzer fixes to the files introduced by the
#3915 (Ethernet L2 transport) and #3916 (runtime schema generation) squash
merges. Removed low-value empty <exception> auto-tags (RCS1140) and restored
the two platform-#if Ethernet channel files (AfPacket/Bpf) that dotnet format
cannot process across TFMs without emitting "Unmerged change" markers.

No behavioural changes; UA.slnx builds 0-warning on net10.0 and the new
project test suites pass.
@marcschier

Copy link
Copy Markdown
Collaborator Author

Squash-merged into part14pubsub (#3892) as commit 606b17a.

@marcschier marcschier closed this Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant