Skip to content

Commit 8eca436

Browse files
authored
Merge P0 SV independent RX diagnostics and VLAN A/B SCL (#325)
Correct tagged/untagged SV Wireshark capture guidance and add checked 4I4V untagged lab reference; lock reference stream parity across toolchains. Preserve immutable M3.H.1 binary release. Hardware receive gate remains open in issue #324.
2 parents 1a298a4 + 83439a4 commit 8eca436

4 files changed

Lines changed: 158 additions & 1 deletion

File tree

‎SUPPORT.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Useful details include the Studio release, Windows version, ESP32-P4 firmware bu
1212

1313
**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.
1414

15-
**Can't see SV in Wireshark?** Verify the isolated Ethernet topology, selected capture interface and whether a switch mirror/TAP is needed.
15+
**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.
1616

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

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<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">
2+
<Header id="ARStack-4I4V-Untagged-Lab"/>
3+
<Communication>
4+
<SubNetwork name="ProcessBus" desc="ARStack untagged Ethernet SV laboratory profile" type="8-MMS">
5+
<ConnectedAP iedName="ARSTACK_MU01" apName="LD0">
6+
<SMV ldInst="MU01" cbName="MSVCB01">
7+
<Address>
8+
<P type="MAC-Address" xsi:type="tP_MAC-Address">01-0C-CD-04-00-01</P>
9+
<P type="APPID" xsi:type="tP_APPID">4000</P>
10+
</Address>
11+
</SMV>
12+
</ConnectedAP>
13+
</SubNetwork>
14+
</Communication>
15+
<IED name="ARSTACK_MU01" desc="ARStack 4I+4V reference merging unit" type="ARStack-SMV-Reference" manufacturer="ARStack61850" configVersion="1.0">
16+
<AccessPoint name="LD0">
17+
<Server>
18+
<LDevice desc="ARStack 4I+4V reference" inst="MU01">
19+
<LN0 desc="ARStack 4I+4V reference" lnClass="LLN0" inst="" lnType="MULLN0_ED1_A1_0">
20+
<DataSet name="PhsMeas1">
21+
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="1" doName="AmpSv" daName="instMag.i" fc="MX"/>
22+
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="1" doName="AmpSv" daName="q" fc="MX"/>
23+
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="2" doName="AmpSv" daName="instMag.i" fc="MX"/>
24+
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="2" doName="AmpSv" daName="q" fc="MX"/>
25+
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="3" doName="AmpSv" daName="instMag.i" fc="MX"/>
26+
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="3" doName="AmpSv" daName="q" fc="MX"/>
27+
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="4" doName="AmpSv" daName="instMag.i" fc="MX"/>
28+
<FCDA ldInst="MU01" prefix="" lnClass="TCTR" lnInst="4" doName="AmpSv" daName="q" fc="MX"/>
29+
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="1" doName="VolSv" daName="instMag.i" fc="MX"/>
30+
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="1" doName="VolSv" daName="q" fc="MX"/>
31+
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="2" doName="VolSv" daName="instMag.i" fc="MX"/>
32+
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="2" doName="VolSv" daName="q" fc="MX"/>
33+
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="3" doName="VolSv" daName="instMag.i" fc="MX"/>
34+
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="3" doName="VolSv" daName="q" fc="MX"/>
35+
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="4" doName="VolSv" daName="instMag.i" fc="MX"/>
36+
<FCDA ldInst="MU01" prefix="" lnClass="TVTR" lnInst="4" doName="VolSv" daName="q" fc="MX"/>
37+
</DataSet>
38+
<SampledValueControl multicast="true" name="MSVCB01" datSet="PhsMeas1" confRev="1" smvID="ARSTACK_SV01" smpRate="4000" smpMod="SmpPerSec" nofASDU="1">
39+
<SmvOpts refreshTime="false" sampleSynchronized="true" sampleRate="false" dataSet="false" security="false" synchSourceId="false"/>
40+
</SampledValueControl>
41+
</LN0>
42+
<LN lnType="CTR-P" lnClass="TCTR" inst="1"/>
43+
<LN lnType="CTR-P" lnClass="TCTR" inst="2"/>
44+
<LN lnType="CTR-P" lnClass="TCTR" inst="3"/>
45+
<LN lnType="CTR-N" lnClass="TCTR" inst="4"/>
46+
<LN lnType="VTR-P" lnClass="TVTR" inst="1"/>
47+
<LN lnType="VTR-P" lnClass="TVTR" inst="2"/>
48+
<LN lnType="VTR-P" lnClass="TVTR" inst="3"/>
49+
<LN lnType="VTR-N" lnClass="TVTR" inst="4"/>
50+
</LDevice>
51+
</Server>
52+
</AccessPoint>
53+
</IED>
54+
<DataTypeTemplates>
55+
<LNodeType id="MULLN0_ED1_A1_0" lnClass="LLN0"/>
56+
<LNodeType id="CTR-P" lnClass="TCTR"><DO name="AmpSv" type="AmpSAV"/></LNodeType>
57+
<LNodeType id="CTR-N" lnClass="TCTR"><DO name="AmpSv" type="AmpSAV"/></LNodeType>
58+
<LNodeType id="VTR-P" lnClass="TVTR"><DO name="VolSv" type="VolSAV"/></LNodeType>
59+
<LNodeType id="VTR-N" lnClass="TVTR"><DO name="VolSv" type="VolSAV"/></LNodeType>
60+
<DOType id="AmpSAV" cdc="SAV">
61+
<DA name="instMag" bType="Struct" type="AnalogueValue" fc="MX"/>
62+
<DA name="q" bType="Quality" fc="MX" qchg="true"/>
63+
</DOType>
64+
<DOType id="VolSAV" cdc="SAV">
65+
<DA name="instMag" bType="Struct" type="AnalogueValue" fc="MX"/>
66+
<DA name="q" bType="Quality" fc="MX" qchg="true"/>
67+
</DOType>
68+
<DAType id="AnalogueValue"><BDA name="i" bType="INT32"/></DAType>
69+
</DataTypeTemplates>
70+
</SCL>

‎docs/INTEROP_FIRST_PACKET.md‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# First SV packet — independent receiver check
2+
3+
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**.
4+
5+
## 1. Confirm SV is actually publishing
6+
7+
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.
8+
9+
## 2. Capture on the receiver's Ethernet adapter
10+
11+
On the same Windows machine used for the analyzer:
12+
13+
1. Select the **physical Ethernet adapter** connected to the ESP32-P4 laboratory network, rather than Wi-Fi or the Npcap loopback adapter.
14+
2. In Wireshark, start a new capture **with no capture filter**. A capture filter is different from a display filter.
15+
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**.
16+
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.
17+
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.
18+
19+
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.
20+
21+
## 3. Compare VLAN-tagged with untagged laboratory SV
22+
23+
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.
24+
25+
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.
26+
27+
**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.
28+
29+
## 4. Interpret the result
30+
31+
| What the receiver PC observes | Next engineering action |
32+
| --- | --- |
33+
| 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. |
34+
| 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. |
35+
| 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. |
36+
| SV decodes in both applications | Compare samples, `smpCnt` rollover and waveform plausibility, then continue to timing/interoperability checks. |
37+
38+
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**.

‎tests/test_scl.cpp‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,6 +1204,54 @@ void parser_detects_duplicate_ieds_and_missing_dataset_references() {
12041204
}));
12051205
}
12061206

1207+
void arstack_untagged_lab_reference_compiles_without_vlan_tag() {
1208+
using namespace ar::iec61850::sampled_values;
1209+
using namespace ar::iec61850::scl;
1210+
1211+
const auto path = std::filesystem::path{ARIEC61850_SOURCE_DIR} /
1212+
"apps" / "arstack_studio" / "templates" /
1213+
"arstack_4i4v_untagged_lab.scd";
1214+
const auto document = SclParser{}.load(path);
1215+
CHECK(document.sampled_values_streams.size() == 1U);
1216+
const auto& stream = document.sampled_values_streams.front();
1217+
CHECK(stream.address.app_id == std::optional<std::uint16_t>{static_cast<std::uint16_t>(0x4000U)});
1218+
CHECK(!stream.address.vlan_id.has_value());
1219+
CHECK(!stream.address.vlan_priority.has_value());
1220+
CHECK(stream.entries.size() == 16U);
1221+
CHECK(stream.sample_rate == 4000U);
1222+
CHECK(stream.no_asdu == 1U);
1223+
1224+
// A/B lab isolation must change only the outer Ethernet VLAN tag.
1225+
// Preserve the shipped reference stream's application identity and data layout.
1226+
const auto reference_path = std::filesystem::path{ARIEC61850_SOURCE_DIR} /
1227+
"apps" / "arstack_studio" / "templates" /
1228+
"arstack_4i4v_9-2le_reference.scd";
1229+
const auto reference_document = SclParser{}.load(reference_path);
1230+
CHECK(reference_document.sampled_values_streams.size() == 1U);
1231+
const auto& reference = reference_document.sampled_values_streams.front();
1232+
CHECK(reference.address.vlan_id == std::optional<std::uint16_t>{static_cast<std::uint16_t>(0U)});
1233+
CHECK(reference.address.vlan_priority == std::optional<std::uint8_t>{static_cast<std::uint8_t>(4U)});
1234+
CHECK(stream.address.destination_mac == reference.address.destination_mac);
1235+
CHECK(stream.address.app_id == reference.address.app_id);
1236+
CHECK(stream.sv_id == reference.sv_id);
1237+
CHECK(stream.configuration_revision == reference.configuration_revision);
1238+
CHECK(stream.sample_rate == reference.sample_rate);
1239+
CHECK(stream.no_asdu == reference.no_asdu);
1240+
CHECK(stream.entries.size() == reference.entries.size());
1241+
1242+
SvPublisherProfileCompileContext context;
1243+
context.profile_family = SvProfileFamily::legacy_9_2le;
1244+
context.sample_counter_modulus = static_cast<std::uint16_t>(4000U);
1245+
const auto compiled = SvPublisherProfileCompiler::compile(stream, context);
1246+
CHECK(compiled.ok());
1247+
CHECK(compiled.profile.has_value());
1248+
CHECK(!compiled.profile->vlan_present);
1249+
CHECK(compiled.profile->app_id == 0x4000U);
1250+
CHECK(compiled.profile->payload_size_bytes == 64U);
1251+
CHECK(compiled.profile->timing.exact_frame_rate_hz() ==
1252+
std::optional<std::uint32_t>{4000U});
1253+
}
1254+
12071255
void parser_detects_editions_from_root_metadata() {
12081256
using namespace ar::iec61850::scl;
12091257

@@ -1281,6 +1329,7 @@ int main() {
12811329
{"Simulator semantic defaults and indexed RCBs", simulator_compiles_semantic_defaults_and_indexed_report_instances},
12821330
{"SCL SettingControl", parser_preserves_setting_control_and_invalid_state},
12831331
{"SCL conflicts and warnings", parser_detects_duplicate_ieds_and_missing_dataset_references},
1332+
{"ARStack untagged SV lab profile", arstack_untagged_lab_reference_compiles_without_vlan_tag},
12841333
{"SCL edition detection", parser_detects_editions_from_root_metadata},
12851334
{"SCL prefixed namespace", parser_supports_prefixed_namespaces_and_predefined_entities},
12861335
{"SCL secure XML", secure_xml_reader_rejects_dtd_entities_and_malformed_documents},

0 commit comments

Comments
 (0)