Documentation
¶
Overview ¶
Package sv decodes IEC 61850-9-2 (and 9-2LE) Sampled Values (SV / SMV) — the substation-automation multicast that streams digitised current and voltage samples from a merging unit (the device that samples the instrument transformers on the primary plant) to the protection and measurement IEDs. SV rides directly over Ethernet (EtherType 0x88BA, no IP / no UDP) at a high, fixed sample rate (4000 or 4800 Hz for 50/60 Hz protection). It is the sampled-measurement sibling of GOOSE (internal/goose, EtherType 0x88B8) and a real substation-security target: SV is unauthenticated by default, so an attacker on the process bus who can inject forged SV frames — replaying an old sample block or spoofing the sample counter — can feed protection relays false current/voltage, triggering or blocking a trip (the SV-injection attack class). A captured SV frame identifies the **stream** (svID — the merging unit), the **sample counter** (smpCnt — the per-sample sequence number that replay/spoof attacks manipulate), the configuration revision, the **synchronisation source** (smpSynch — whether the samples are GPS-disciplined) and surfaces the raw sampled-value block, which is the recon headline for process-bus reconnaissance.
Wrap-vs-native judgement ¶
Native. SV is the same shape as GOOSE: an 8-byte APPID / length / reserved header followed by an ASN.1 BER-encoded savPdu (outer tag 0x60) whose seqASDU (tag 0xA2) holds one or more ASDUs (each a 0x30 SEQUENCE of IMPLICIT context-tagged fields). A deterministic BER tag/length/value walk, reusing the same approach as internal/goose; stdlib only, no new go.mod dep.
Verifiable / no confidently-wrong output ¶
The savPdu / ASDU tag layout follows the authoritative IEC 61850-9-2 ASN.1 (and matches Wireshark's sv dissector) — there is no scapy model for SV (nor for GOOSE), so verification is by the deterministic, byte-checkable BER walk against spec-built vectors. Only the standardised envelope is decoded: svID, smpCnt, confRev, smpSynch, datSet, refrTm, smpRate, smpMod; the **sampled-value data block itself (the `sample` OCTET STRING) is dataset-configuration-dependent and is surfaced as raw hex** (decoding individual channel values would be confidently-wrong without the dataset definition), exactly as GOOSE surfaces allData. The security field (IEC 62351) is surfaced raw. A missing 0x60 outer tag or a truncated TLV is reported, not guessed.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ASDU ¶
type ASDU struct {
SvID string `json:"sv_id,omitempty"`
DatSet string `json:"dat_set,omitempty"`
SmpCnt int `json:"smp_cnt"`
ConfRev int64 `json:"conf_rev,omitempty"`
RefrTimeHex string `json:"refr_time_hex,omitempty"`
SmpSynch int `json:"smp_synch"`
SmpSynchName string `json:"smp_synch_name,omitempty"`
SmpRate int `json:"smp_rate,omitempty"`
SampleHex string `json:"sample_hex,omitempty"`
SmpMod int `json:"smp_mod,omitempty"`
}
ASDU is one Application-Specific Data Unit within the savPdu's seqASDU.
type Result ¶
type Result struct {
TotalBytes int `json:"total_bytes"`
// SV header (after the 0x88BA EtherType).
APPID int `json:"appid"`
Length int `json:"length"`
Reserved1 int `json:"reserved1"`
Reserved2 int `json:"reserved2"`
NoASDU int `json:"no_asdu"`
SecurityHex string `json:"security_hex,omitempty"`
ASDUs []ASDU `json:"asdus,omitempty"`
Notes []string `json:"notes,omitempty"`
}
Result is the structured decode of an IEC 61850-9-2 Sampled Values message.