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
2 changes: 1 addition & 1 deletion SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Useful details include the Studio release, Windows version, ESP32-P4 firmware bu

**Can't find the board?** Check the USB data cable and serial device selection; use **Configuration → Firmware** to verify the ESP32-P4 and install matching firmware.

**Can't see SV in Wireshark?** Verify the isolated Ethernet topology, selected capture interface and whether a switch mirror/TAP is needed.
**SMV missing in ARSAS, DigSubAnalyzer or Wireshark?** Follow the [independent Ethernet receiver check](docs/INTEROP_FIRST_PACKET.md): verify SV RUNNING, capture on the actual NIC, and compare priority-tagged VLAN 0 with the optional untagged lab SCL.

**Interested in IEC 61850 subscriber testing?** Share results in the [community interoperability guide](docs/COMMUNITY_TESTING.md).

Expand Down
70 changes: 70 additions & 0 deletions apps/arstack_studio/templates/arstack_4i4v_untagged_lab.scd
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<SCL xmlns="http://www.iec.ch/61850/2003/SCL" xmlns:sxy="http://www.iec.ch/61850/2003/SCLcoordinates" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.iec.ch/61850/2003/SCL SCL.xsd http://www.iec.ch/61850/2003/SCLcoordinates">
<Header id="ARStack-4I4V-Untagged-Lab"/>
<Communication>
<SubNetwork name="ProcessBus" desc="ARStack untagged Ethernet SV laboratory profile" type="8-MMS">
<ConnectedAP iedName="ARSTACK_MU01" apName="LD0">
<SMV ldInst="MU01" cbName="MSVCB01">
<Address>
<P type="MAC-Address" xsi:type="tP_MAC-Address">01-0C-CD-04-00-01</P>
<P type="APPID" xsi:type="tP_APPID">4000</P>
</Address>
</SMV>
</ConnectedAP>
</SubNetwork>
</Communication>
<IED name="ARSTACK_MU01" desc="ARStack 4I+4V reference merging unit" type="ARStack-SMV-Reference" manufacturer="ARStack61850" configVersion="1.0">
<AccessPoint name="LD0">
<Server>
<LDevice desc="ARStack 4I+4V reference" inst="MU01">
<LN0 desc="ARStack 4I+4V reference" lnClass="LLN0" inst="" lnType="MULLN0_ED1_A1_0">
<DataSet name="PhsMeas1">
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="1" doName="AmpSv" daName="instMag.i" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="1" doName="AmpSv" daName="q" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="2" doName="AmpSv" daName="instMag.i" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="2" doName="AmpSv" daName="q" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="3" doName="AmpSv" daName="instMag.i" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="3" doName="AmpSv" daName="q" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="4" doName="AmpSv" daName="instMag.i" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="4" doName="AmpSv" daName="q" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="1" doName="VolSv" daName="instMag.i" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="1" doName="VolSv" daName="q" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="2" doName="VolSv" daName="instMag.i" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="2" doName="VolSv" daName="q" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="3" doName="VolSv" daName="instMag.i" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="3" doName="VolSv" daName="q" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="4" doName="VolSv" daName="instMag.i" fc="MX"/>
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="4" doName="VolSv" daName="q" fc="MX"/>
</DataSet>
<SampledValueControl multicast="true" name="MSVCB01" datSet="PhsMeas1" confRev="1" smvID="ARSTACK_SV01" smpRate="4000" smpMod="SmpPerSec" nofASDU="1">
<SmvOpts refreshTime="false" sampleSynchronized="true" sampleRate="false" dataSet="false" security="false" synchSourceId="false"/>
</SampledValueControl>
</LN0>
<LN lnType="CTR-P" lnClass="TCTR" inst="1"/>
<LN lnType="CTR-P" lnClass="TCTR" inst="2"/>
<LN lnType="CTR-P" lnClass="TCTR" inst="3"/>
<LN lnType="CTR-N" lnClass="TCTR" inst="4"/>
<LN lnType="VTR-P" lnClass="TVTR" inst="1"/>
<LN lnType="VTR-P" lnClass="TVTR" inst="2"/>
<LN lnType="VTR-P" lnClass="TVTR" inst="3"/>
<LN lnType="VTR-N" lnClass="TVTR" inst="4"/>
</LDevice>
</Server>
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType id="MULLN0_ED1_A1_0" lnClass="LLN0"/>
<LNodeType id="CTR-P" lnClass="TCTR"><DO name="AmpSv" type="AmpSAV"/></LNodeType>
<LNodeType id="CTR-N" lnClass="TCTR"><DO name="AmpSv" type="AmpSAV"/></LNodeType>
<LNodeType id="VTR-P" lnClass="TVTR"><DO name="VolSv" type="VolSAV"/></LNodeType>
<LNodeType id="VTR-N" lnClass="TVTR"><DO name="VolSv" type="VolSAV"/></LNodeType>
<DOType id="AmpSAV" cdc="SAV">
<DA name="instMag" bType="Struct" type="AnalogueValue" fc="MX"/>
<DA name="q" bType="Quality" fc="MX" qchg="true"/>
</DOType>
<DOType id="VolSAV" cdc="SAV">
<DA name="instMag" bType="Struct" type="AnalogueValue" fc="MX"/>
<DA name="q" bType="Quality" fc="MX" qchg="true"/>
</DOType>
<DAType id="AnalogueValue"><BDA name="i" bType="INT32"/></DAType>
</DataTypeTemplates>
</SCL>
38 changes: 38 additions & 0 deletions docs/INTEROP_FIRST_PACKET.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# First SV packet — independent receiver check

Use this when ARStack Studio reports SV publishing but ARSAS or DigSubAnalyzer shows no Sampled Values. The goal is to identify whether the frame is **missing from the receiving Ethernet interface** or **arriving but not being decoded**.

## 1. Confirm SV is actually publishing

Connect the ESP32-P4 to an **isolated laboratory Ethernet network**. Open ARStack Studio and confirm **SV RUNNING** with increasing transmit/frame counts. PTP RUNNING alone does not mean SV frames are being transmitted.

## 2. Capture on the receiver's Ethernet adapter

On the same Windows machine used for the analyzer:

1. Select the **physical Ethernet adapter** connected to the ESP32-P4 laboratory network, rather than Wi-Fi or the Npcap loopback adapter.
2. In Wireshark, start a new capture **with no capture filter**. A capture filter is different from a display filter.
3. While Studio is publishing, apply the **display filter** `eth.type == 0x88ba || vlan.etype == 0x88ba`. This covers both plain SV Ethernet frames and SV inside an 802.1Q priority/VLAN tag. The outer `eth.type` may be `0x8100` for tagged frames, so `eth.type == 0x88ba` **alone is not sufficient**.
4. Record whether SV frames appear and whether packet details show `APPID`, `svID`, `smpCnt`, destination MAC and, where present, VLAN ID/PCP. Check the actual packet bytes, not only the configured SCL; NIC VLAN offload/stripping can change what a host capture exposes.
5. Save **3–5 seconds** of traffic as `.pcapng` or `.pcap` with **no capture filter**, along with the selected NIC name, physical topology, Studio/firmware versions, analyzer versions and chosen stream filters. Remove confidential project information before sharing.

The reference M3.H profile uses APPID `0x4000`, destination `01:0C:CD:04:00:01` and approximately **4,000 frames/s**. The stream ID depends on the profile deployed by Studio; do not assume a specific `svID` without examining the wire.

## 3. Compare VLAN-tagged with untagged laboratory SV

The included **reference SCL** requests Ethernet **802.1Q priority tagging**: VLAN ID `0`, PCP `4`. Some PC network or switch paths handle priority-tagged traffic differently.

For diagnosis only, an alternative [untagged 4I+4V SCL](../apps/arstack_studio/templates/arstack_4i4v_untagged_lab.scd) keeps the same APPID, multicast MAC, data-set and sample rate **but omits VLAN tagging**. In Studio, stop publishing, load this SCL, select/deploy its SV stream and restart. Compare the receiving capture against the original configuration.

**Do not change the VLAN scheme on an operating substation network.** This is an isolated-bench comparison to identify an Ethernet capture path difference; a change in receive behavior is evidence about the path, not proof of an arbitrary SV protocol fault.

## 4. Interpret the result

| What the receiver PC observes | Next engineering action |
| --- | --- |
| No plain or VLAN-encapsulated SV frames on the selected adapter | Check board link, Studio TX state, adapter choice, switch mirror/TAP, NIC VLAN offload and tagged VLAN forwarding. First confirm the combined display filter was used. |
| SV appears in Wireshark but not in DigSubAnalyzer | Note raw frame and decoder counters and share the capture; inspect Npcap filter and raw BER path. |
| SV appears in Wireshark but ARSAS snapshot stays empty | Use ARSAS's **First received SV stream** option (when available), or match selected SCL APPID/MAC/`svID` to the actual packet. |
| SV decodes in both applications | Compare samples, `smpCnt` rollover and waveform plausibility, then continue to timing/interoperability checks. |

Open [P0 receiver acceptance issue #324](https://github.com/masarray/arstack61850/issues/324) for incident tracking. A self-decoded PCAP from Studio cannot replace an **independent RX capture from the affected NIC**.
49 changes: 49 additions & 0 deletions tests/test_scl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1204,6 +1204,54 @@ void parser_detects_duplicate_ieds_and_missing_dataset_references() {
}));
}

void arstack_untagged_lab_reference_compiles_without_vlan_tag() {
using namespace ar::iec61850::sampled_values;
using namespace ar::iec61850::scl;

const auto path = std::filesystem::path{ARIEC61850_SOURCE_DIR} /
"apps" / "arstack_studio" / "templates" /
"arstack_4i4v_untagged_lab.scd";
const auto document = SclParser{}.load(path);
CHECK(document.sampled_values_streams.size() == 1U);
const auto& stream = document.sampled_values_streams.front();
CHECK(stream.address.app_id == std::optional<std::uint16_t>{static_cast<std::uint16_t>(0x4000U)});
CHECK(!stream.address.vlan_id.has_value());
CHECK(!stream.address.vlan_priority.has_value());
CHECK(stream.entries.size() == 16U);
CHECK(stream.sample_rate == 4000U);
CHECK(stream.no_asdu == 1U);

// A/B lab isolation must change only the outer Ethernet VLAN tag.
// Preserve the shipped reference stream's application identity and data layout.
const auto reference_path = std::filesystem::path{ARIEC61850_SOURCE_DIR} /
"apps" / "arstack_studio" / "templates" /
"arstack_4i4v_9-2le_reference.scd";
const auto reference_document = SclParser{}.load(reference_path);
CHECK(reference_document.sampled_values_streams.size() == 1U);
const auto& reference = reference_document.sampled_values_streams.front();
CHECK(reference.address.vlan_id == std::optional<std::uint16_t>{static_cast<std::uint16_t>(0U)});
CHECK(reference.address.vlan_priority == std::optional<std::uint8_t>{static_cast<std::uint8_t>(4U)});
CHECK(stream.address.destination_mac == reference.address.destination_mac);
CHECK(stream.address.app_id == reference.address.app_id);
CHECK(stream.sv_id == reference.sv_id);
CHECK(stream.configuration_revision == reference.configuration_revision);
CHECK(stream.sample_rate == reference.sample_rate);
CHECK(stream.no_asdu == reference.no_asdu);
CHECK(stream.entries.size() == reference.entries.size());

SvPublisherProfileCompileContext context;
context.profile_family = SvProfileFamily::legacy_9_2le;
context.sample_counter_modulus = static_cast<std::uint16_t>(4000U);
const auto compiled = SvPublisherProfileCompiler::compile(stream, context);
CHECK(compiled.ok());
CHECK(compiled.profile.has_value());
CHECK(!compiled.profile->vlan_present);
CHECK(compiled.profile->app_id == 0x4000U);
CHECK(compiled.profile->payload_size_bytes == 64U);
CHECK(compiled.profile->timing.exact_frame_rate_hz() ==
std::optional<std::uint32_t>{4000U});
}

void parser_detects_editions_from_root_metadata() {
using namespace ar::iec61850::scl;

Expand Down Expand Up @@ -1281,6 +1329,7 @@ int main() {
{"Simulator semantic defaults and indexed RCBs", simulator_compiles_semantic_defaults_and_indexed_report_instances},
{"SCL SettingControl", parser_preserves_setting_control_and_invalid_state},
{"SCL conflicts and warnings", parser_detects_duplicate_ieds_and_missing_dataset_references},
{"ARStack untagged SV lab profile", arstack_untagged_lab_reference_compiles_without_vlan_tag},
{"SCL edition detection", parser_detects_editions_from_root_metadata},
{"SCL prefixed namespace", parser_supports_prefixed_namespaces_and_predefined_entities},
{"SCL secure XML", secure_xml_reader_rejects_dtd_entities_and_malformed_documents},
Expand Down
Loading