DNP3 IIN flags explained: what each bit means and what to check
Every DNP3 response, solicited or unsolicited, carries two bytes called the Internal Indications (IIN). They are the outstation's way of telling the master how it feels without being asked: it has events waiting, it needs its clock set, it just restarted, it lost events. Reading them correctly is the fastest way to see what is wrong with an RTU from a capture, because a flag that stays set for hours is almost always a master that is not doing its part.
Where they are in the frame
In the application layer, a response starts with the application control byte and the function code (0x81 for a response, 0x82 for an unsolicited response), followed by the two IIN bytes, IIN1 and IIN2, and then the objects. A response whose IIN bytes are 10 00 has IIN1 = 0x10, which is NEED_TIME. 80 08 is DEVICE_RESTART in IIN1 plus EVENT_BUFFER_OVERFLOW in IIN2.
IIN1
| Bit | Mask | Name | Meaning |
|---|---|---|---|
| 0 | 0x01 | BROADCAST | The request this answers was a broadcast. |
| 1 | 0x02 | CLASS_1_EVENTS | The outstation holds class 1 events the master has not read. |
| 2 | 0x04 | CLASS_2_EVENTS | Same, class 2. |
| 3 | 0x08 | CLASS_3_EVENTS | Same, class 3. |
| 4 | 0x10 | NEED_TIME | The outstation wants its clock set. |
| 5 | 0x20 | LOCAL_CONTROL | Some outputs are in local mode and will not take remote commands. |
| 6 | 0x40 | DEVICE_TROUBLE | An abnormal condition, whose meaning is device-specific. |
| 7 | 0x80 | DEVICE_RESTART | The device restarted and the master has not acknowledged it yet. |
IIN2
| Bit | Mask | Name | Meaning |
|---|---|---|---|
| 0 | 0x01 | NO_FUNC_CODE_SUPPORT | The function code in the request is not implemented. |
| 1 | 0x02 | OBJECT_UNKNOWN | A requested object (group and variation) is not implemented. |
| 2 | 0x04 | PARAMETER_ERROR | A parameter, such as an index or a range, is invalid. |
| 3 | 0x08 | EVENT_BUFFER_OVERFLOW | At least one event buffer overflowed: events were lost. |
| 4 | 0x10 | ALREADY_EXECUTING | The request is already being executed (a repeated control, for example). |
| 5 | 0x20 | CONFIG_CORRUPT | The outstation's configuration is corrupt. |
| 6, 7 | - | Reserved | Always zero. |
Patterns worth looking for in a capture
DEVICE_RESTART on every response
The flag is raised when the outstation boots and stays up until the master clears it by writing IIN1 bit 7 to zero (a WRITE of group 80, variation 1, index 7). If you see it on every response for the whole capture, the master never clears it. It is harmless to the data, but it hides a real restart the next time one happens, and it is the first thing worth fixing on a noisy link.
NEED_TIME that never goes away
The outstation asks for its time; the master is supposed to answer with a time-sync procedure. If the flag stays set, either the master is not synchronizing at all, or its write is being rejected. Look for the WRITE of the Time and Date object (group 50) and check the IIN2 of the answer: PARAMETER_ERROR or NO_FUNC_CODE_SUPPORT means the outstation refused it. Many outstations also raise it again on their own schedule (their time-sync interval), so seeing it return after hours is normal. Seeing it return within minutes of a sync the outstation accepted points to a clock that cannot hold the time.
CLASS_x_EVENTS stuck high
These bits say "there is something to read in this class". They should drop after the master's next event poll. If one stays set across several polls, the master is not polling that class (a common configuration slip), or its event poll is built for a different class than the one the outstation fills.
EVENT_BUFFER_OVERFLOW
Events were dropped because they were produced faster than the master collected them, or because a noisy point filled the buffer. Two things to check: how often the master polls events, and which point generates the most events (a chattering input or a deadband that is too tight). After an overflow the master cannot trust its event history, so an integrity poll (class 0, 1, 2, 3) is the way to resynchronize.
OBJECT_UNKNOWN and PARAMETER_ERROR
The master is asking for something the outstation does not have: a group or variation it does not implement, or an index beyond its point count. The poll configuration was probably copied from another device. Trim it to what the outstation's device profile lists.
LOCAL_CONTROL
Someone left a switch in local on the device. Remote commands will be refused until it goes back to remote, which makes it a field problem, not a protocol one.
Doing this on a real capture
Reading IIN bytes by hand in a hex dump works for one frame and gets tedious for ten thousand. ComputingSphere DNP3 decodes a pcap, groups it by RTU, and shows which IIN flags each RTU raised, how often and when, next to the polling and event statistics around them. It only reads what already went over the wire and never touches the network. You can also decode a single frame without an account, and the Free plan covers 1,000 messages a month.
Reference
The IIN bits are defined in IEEE Std 1815 (DNP3). Device-specific meanings, such as what DEVICE_TROUBLE stands for, are in the outstation's device profile document.