Pick the wrong service type and the network still works — until it doesn’t. Under light load everything delivers. Under load, the acknowledged multicast you specified starts eating the channel it needs, and the symptom looks like a hardware fault.
ISO/IEC 14908-1 gives you four services. This is what each one actually does on the wire, when to use it, and how to set the retry counts and timers that go with it.
Table of Contents
Start here
| Confirms delivery? | Returns data? | Group limit | Cost on the channel | |
|---|---|---|---|---|
| Acknowledged | Yes | No | 64 | High — every member replies |
| Request/response | Yes | Yes | 64 | High |
| Unacknowledged-repeated | No | No | Domain size | Fixed — retries always sent |
| Unacknowledged | No | No | Domain size | Lowest — one packet |
The useful way to read that table is the last two columns together. Acknowledged service costs you n replies for a group of n. Unacknowledged-repeated costs you the same handful of packets whether the group has three members or three hundred.
Acknowledged
The sender transmits. Every addressed recipient must acknowledge. The sender retries until it has them all or exhausts its retry count.
The transport layer tells the link layer how many acknowledgements to expect, and that number goes into the link layer header — which is what lets every other device on the channel widen its backlog estimate before the replies arrive.
Works with address formats #1 (group), #2a (unicast), and to a limited extent #3.
The group-size trap. If you multicast to a group the sender is not a member of, and the service needs acknowledgements, the transport layer has to be told the group size is the actual size plus one. Get this wrong and the sender either waits for an acknowledgement that isn’t coming or stops one short.
Request/response
Same reliability shape, but the reply carries data rather than just confirming arrival. This is a remote procedure call, and it’s what a network variable poll uses underneath.
The idempotent rule is the thing to know. The protocol decides whether a transaction may be executed more than once purely from the size of its response:
- Response of 1 byte or less → non-idempotent → executed at most once
- Response of more than 1 byte → idempotent → may be executed zero or more times
Nothing about the request itself enters into it. The standard makes the split on response size to bound how much storage a device needs for transaction records, and it gives the example that separates the two cases cleanly: “open the valve an additional 10 %” depends on prior state and must run once; “read the first 10 table values” can run any number of times with the same result.
So if you write a command with a side effect and give it a chatty response, the protocol will let a retry execute it twice. If you need a long response and at-most-once execution, the application has to save the response and resend it. The session layer helps by telling the application layer when a request is a duplicate — but it is the application’s job to act on that.
A request/response transaction fails if the server doesn’t produce its response inside the timer and retry budget.
Unacknowledged-repeated
Identical to acknowledged on the wire, with one difference: nothing acknowledges it. The sender simply transmits the message repeatedly until the repetition count equals the retry count.
Two consequences make this the most under-used service in the set.
No 64-member limit. With no acknowledgements to collect, group size is bounded only by the number of devices in the domain.
It can be more reliable than acknowledged service. The standard says this directly: where acknowledgements to a multicast would take a significant share of channel bandwidth, a message is more likely to be delivered properly using unacknowledged-repeated than acknowledged multicast. The acknowledged service congests the channel it depends on. The repeated service doesn’t.
There’s a neat detail in how it handles backlog. The first transmission declares a backlog increment equal to the retry count — telling the channel up front how many more packets are coming. Every subsequent transmission in the transaction declares zero, because it’s already accounted for.
Unacknowledged
Sent once. No TPDU header at all, which means no duplicate detection. Nothing comes back.
Use it where loss is acceptable and repetition is inherent — periodic values that will be sent again shortly anyway.
Reminders: how large groups get acknowledged
When a multicast is outstanding, the sender doesn’t blindly resend the whole message to everyone. It solicits acknowledgements selectively, and the mechanism switches based on group member numbers.
Highest acknowledged member below 16 → a REM/MSG reminder carrying both a member list and the message. The member list is a bit array: a 0 in position X means member X hasn’t acknowledged, a 1 means it has. Bits run right to left within a byte, from bit zero. A length of 0 means the field is absent and everyone should acknowledge. The declared backlog increment is the count of acknowledgements still outstanding.
Highest acknowledged member 16 or above → a plain reminder with no message attached, followed by the message itself. The pair does the same job as the combined form. The split exists purely to cap the maximum TPDU size for large groups. The plain reminder declares a backlog increment of zero; the message that follows declares the outstanding count.
Acknowledgements themselves are null TPDUs. They use format #2a for unicast or #2b for group, and they inherit the priority and alternate-path attributes of the original message.
Retries and timers
Retry count. The field is 4 bits, so 0 to 15, and total attempts is retries plus one. The standard caps it at 15 and then says plainly that 2 to 5 covers most situations in practice.
It also gives you the maths. For single-attempt failure probability p and group size n, the probability of completing within k retries follows a binomial expansion, with a note defining p for a single channel as 1/2w + pe — where w is the MAC randomising window size and pe is the probability of loss from transmission error. Larger group, more retries needed for the same confidence.
The pragmatic advice attached to it is worth taking: don’t use a large retry count on transactions that repeat periodically anyway. The next cycle is your retry.
Three timers. One is active on each side of a transaction.
| Timer | Side | Job |
|---|---|---|
Xmit_Timer | Sender | Retransmission interval for acknowledged service |
Repeat_Interval_Timer | Sender | Gap between repeats for unacknowledged-repeated |
Rcv_Timer | Receiver | How long a receive record is held |
The standard’s calculation methodology, for unicast on a single channel:
Retry_Count = 2 to 5
Xmit_Timer ≥ 3 × packet cycle time + margin
Rcv_Timer ≥ Xmit_Timer × (Retry_Count + 2)
The reasoning behind the 3× is spelled out: two packet cycles for the average device to get channel access, one more for the transmission itself, then a margin covering how long the receiver takes to process and reply — which depends on clock speeds at both ends.
Worked through for a twisted-pair channel, where the average packet cycle is 4 020 µs: Xmit_Timer lands above roughly 12 ms, and with a retry count of 4, Rcv_Timer lands above roughly 72 ms.
Three adjustments the standard flags:
- Multicast transactions need longer receive timer values than unicast, because they take longer to complete even with no retries.
- Multi-channel networks depend on router speed and buffer counts — the single-channel formula doesn’t hold.
- Anything addressed by Unique_Node_ID uses a fixed 8-second receive timer, regardless of the configured non-group value.
Because buffering and clock rates are adjustable, the standard’s final word on this is that the system designer has to take measurements. The formulas are a starting point, not an answer.
Xmit_Timer resets on every acknowledgement or authentication challenge received — not once per expiry period. Rcv_Timer resets whenever a message or reminder arrives carrying a new transaction number for that destination.
What goes wrong
Receive record exhaustion. A device holds a shared pool of receive records, and the pool size caps how many transactions it can handle concurrently within the receive timer window. Run out and nothing visibly fails — a “receive transaction full” statistic increments and the transaction is dropped. A device that misbehaves only under burst load is worth checking here. The pool should be sized to the number of concurrent transactions expected inside Rcv_Timer.
The reset window. Duplicate detection holds up in every case except one: a device that has just reset starts again at transaction number 0. A transaction in flight across that reset may end up acknowledged by the receiver without ever being acted on. Nothing reports this.
Alternate path on the last two attempts. The transport layer sets the alternate path bit on the final two attempts of a transaction. If your channel has a redundant path, the tail of a failing transaction behaves differently from the head — worth knowing before you conclude a fault is intermittent.
Reserved codes. TPDU type codes 3, 6, and 7 are reserved, and packets carrying them are discarded silently.
FAQ
Which service should I use for a network variable binding?
Acknowledged for anything where you need to know it arrived and the group is small. Unacknowledged-repeated for large groups or high-rate values. Unacknowledged for periodic values that will be resent shortly anyway.
Why is my acknowledged multicast slower than an unacknowledged one?
Because every member replies. For a group of n, one message becomes n acknowledgements plus any reminders. On a loaded channel those replies compete with the traffic you’re trying to deliver.
Can I authenticate an unacknowledged message?
No. Only a TPDU that requires an acknowledgement can carry the authentication bit, which means acknowledged and request/response only.
What retry count should I set?
Start at 2 to 5. Increase for larger groups or noisier channels, decrease for periodic transactions where the next cycle is effectively a retry. Beyond that, measure.
Are groups one-way?
No. Groups are symmetric — every member can both send and receive.
Why did my command execute twice?
Almost certainly the idempotent rule. A response longer than one byte makes the transaction idempotent, and an idempotent transaction may be executed more than once. Shorten the response to one byte, or handle duplicate notification in the application.
