A packet capture is the only record of what actually crossed the wire. It is also the most over-claimed artefact in substation work: people treat “we have a capture” as if it were “we have a result”. This note separates the two.

Why the capture is the only witness

A configuration file records intent. A device screen records an interpretation. Only the wire records behaviour: the bytes, in order, with timestamps. That is why every serious claim about a substation network eventually lands on a capture — and why a tool that cannot read one is describing a system it has not seen.

The mistake starts one step later. A capture proves that something happened. It does not prove that what happened was correct, complete, or caused by what you think.

What a GOOSE capture can prove

Read field by field, a capture answers a specific set of questions with no interpretation required:

Question What in the frame answers it
Was the message actually published? The frame exists, with a timestamp
Which stream is it? Destination MAC, APPID, VLAN ID and priority
Which control block, and which version of it? gocbRef, datSet, confRev
Is this a new state or a retransmission? stNum and sqNum
Is the publisher keeping its declared rhythm? Intervals against timeAllowedToLive
Does the frame match the configuration? Field values compared with the SCD, not with memory

None of those rows needs the standard’s blessing. They are observations, and they are checkable by a second person with the same file.

What a capture cannot prove

This list is the important one, because every item on it has been presented as proven by a capture somewhere:

  • Conformance. A capture shows one exchange, not compliance with a standard. Conformance is a test against requirements, normally by an accredited laboratory.
  • Why the publisher sent it. The frame is the output of internal state you cannot see; you can infer, you cannot know.
  • That nothing else is wrong. The capture has a window. Behaviour outside it is unobserved, and “no errors in the file” is not “no errors”.
  • That your own implementation is interoperable. A capture of a peer shows the peer. It says nothing about whether your encoder writes what that peer would accept.
  • Who produced the capture. Unless the file states the product and version, it is anonymous bytes — useful, but not attributable.
  • Anything about a different protocol. GOOSE timing says nothing about sampled values, and an MMS read says nothing about a trip circuit.

Five things to record with every capture

A capture without this header becomes an anecdote within a week. The header costs five minutes:

Field Why it matters
Who produced it Product and version; “a relay” is not a source
When, and for how long The window is part of the evidence
How it was taken Port mirror, TAP, or a host capture — each has blind spots
Clock source Timestamps are only comparable if the clock is known
What was supposed to happen The test intent, so “pass” has a definition

An anonymised capture is still evidence. A capture with no provenance is a rumour with a checksum.

The case that changed how we test

In the project behind this note, the protocol tests were symmetric: our encoder produced bytes, our decoder read them back, and the tests passed. Five wire-format defects survived that arrangement, because both sides shared the same mistake.

Defect What symmetric tests showed What foreign bytes showed
Identifier encoded as an OCTET STRING green a conformant peer reads a different type
Conclude with wrong choice tags green the release silently fails
Name-list service tags one too high green the request is not recognised
Read-Request access read from the wrong field green an empty list, no error
Session/presentation/ACSE layers skipped green no association at all

The lesson is not “write more tests”. It is that a test written from one implementation’s output cannot find a mistake that implementation makes. The fix was to pin assertions to bytes produced by another implementation.

Turning a capture into evidence

Four rules, in order. Skip one and the evidence weakens:

  • The assertion must fail before the fix. Otherwise you have described the current behaviour, not found a defect.
  • The bytes under assertion must come from a different implementation. Your own output is a regression test, not evidence.
  • The file is hashed and kept. A result that cannot be re-run against the same bytes is a memory.
  • The limits are written down. What the capture does not cover belongs next to what it does.

What this means in practice

For an engineer: when someone hands you a capture, ask for the header before the analysis. For a vendor: if a page claims interoperability, ask which peer, which version, and whether a peer ever accepted your request. The answer is usually shorter than the page.

In the tool described on this site, the position is deliberate and uncomfortable: a capture of a peer is not proof that our own requests are accepted. That is why the interoperability claim is still open, and why the evidence page says so in plain words.

A capture is evidence about a moment, not a verdict about a system. The difference is the whole discipline.

The canonical version, with the Persian translation: https://rezafarsi.com/en/articles/goose-capture-evidence/