Copyright (C) 2017 Nest Labs, All Rights Reserved
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This document describes a reliability protocol for both stream and frame based protocols. It has the following design parameters:
- Designed to be sent over a frame transport mechanism. May be
encoded with HDLC-lite for UART, or using some sort of SPI
framing protocol (like this one). This protocol makes
the following assumptions about the upper framing layer:
- The upper framing layer is best-effort.
- The upper framing layer includes some sort of CRC checking. If the CRC fails, the packet is dropped and some sort of notification is sent to the MASRP layer.
- Supports the transport of frames or streams.
- No payload length. The length of the frame is implied by the framing mechanism.
- Optional capability to support multiple independent asynchronous streams (multiplexing).
- MTU discovery.
- Control Byte:
- 2-bits for Frame Type
- 3-bits for OFC (Outbound Frame Counter)
- 3-bits for AFC (Acknowledged Frame Counter)
- Payload Bytes (defined by frame type)
0
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|TYP| OFC | AFC |
+-+-+-+-+-+-+-+-+
The smallest possible frame is a single byte: A control byte with a zero-length payload.
The frame types are:
- 0 - REQ - Control Request
- 1 - RSP - Control Response
- 2 - ACK - Acknowledgement (May rename to DAT)
- 3 - NAK - Negative Acknowledgement (Bad CRC, flow control, etc)
For a control request/response, the payload is formatted as follows:
- Control Request Info byte:
- 1 bit (reserved for REQ, set-on-error for RSP)
- 3 bits reserved (set to zero. Middle bit will always set to zero)
- 4 bits request type:
- 0 - RESET
- All other values - RESERVED
- Request-type-specific payload
For a RESET, the payload is formatted as follows:
- 1 byte:
- 4 bits for supported protocol version. (zero is experimental, one is the first published version of this protocol)
- 4 bits for protocol reset reason:
- 0: MASRP layer Reset
- 1: Power-On Reset
- 2: External Reset
- 3: Software Reset
- 4: System Crash
- 5-15: Reserved
- 1 byte for the maximum receivable frame size (calculated as
MFS
minus 16). Valid values are between 0-127, meaning the maximum frame size is between 16 and 143 bytes. Values larger than 127 are reserved: if encountered, assume a max receivable frame size of 143.
Reset packets indicate that the OFC is reset to the value of the OFC field.
For an ACK/NAK, (which contain actual stream content), the payload is formatted as follows:
- 1 byte:
- 3 bits reserved, set to zero.
- 1 bit, FRAME_INCOMPLETE. This is used if the enclosed stream is frame-based. When this bit is not set, the entire frame is considered to be the concatenation of all of the prior subframes that have this bit set.
- 1 bit, URG (urgent data flag. Used for things like sending CTRL-C, etc)
- 3 bits for stream id (MUX support). If MUX is not supported, skip frames which have this set to a non-zero value and always set these bits to zero when sending.
- Payload data
When an ACK/NAK has a payload, the OFC value is incremented. An
ACK/NAK without a payload uses the largest previously sent OFC value.
REQ and RSP have similar semantics to ACK/NAKs without a
payload---they do not change the OFC or AFC.
All mathmatical operations performed on frame counters are modulo 8. I.E.:
$7 + 1 = 0 MOD 8$
Valid AFC/OFC combinations for a control reset request:
RST_REQ_70
: AFC:7, OFC:0 (Initial sender)RST_REQ_01
: AFC:0, OFC:1 (After having received and responded to a reset)
Valid AFC/OFC combinations for a control reset response:
RST_RSP_00
: AFC:0, OFC:0 (Response sent before sending reset)RST_RSP_01
: AFC:0, OFC:1 (Response sent after sending reset, but before a response was received from other device)RST_RSP_11
: AFC:1, OFC:1 (Response sent after sending reset, after having received and responded to a reset)
No matter what path initialization goes through, once initialization is complete, the first data packet sent will have an AFC of 1 and an OFC of 1.
Upon receiving one of the reset messages, a device must behave in the following predefined ways:
-
Receiving
RST_REQ_70
:- If already sent
RST_REQ_70
,- Send
RST_RSP_01
- Send
- Otherwise RESET LOCAL STATE and send
RST_RSP_00
and thenRST_REQ_01
- If already sent
-
Receiving
RST_RSP_00
- If already sent
RST_REQ_70
,- WAIT FOR
RST_REQ_01
- WAIT FOR
- Otherwise RESET LOCAL STATE and send
RST_REQ_70
- If already sent
-
Receiving
RST_REQ_01
- If already RECEIVED
RST_RSP_00
- Send
RST_RSP_11
- You are now RUNNING.
- Send
- Otherwise RESET LOCAL STATE and send
RST_REQ_70
- If already RECEIVED
-
Receiving
RST_RSP_01
- If already sent
RST_REQ_70
- You are now RUNNING.
- Otherwise RESET LOCAL STATE and send
RST_REQ_70
- If already sent
-
Receiving
RST_RSP_11
- If already sent
RST_REQ_01
- You are now RUNNING.
- Otherwise RESET LOCAL STATE and send
RST_REQ_70
- If already sent
Summary:
- Device A sends
RST_REQ_70
- Device B sends
RST_RSP_00
- Device B sends
RST_REQ_01
- Device A sends
RST_RSP_11
Details:
Device | Type | AFC | OFC | Payload Description | State |
---|---|---|---|---|---|
Device A | - | - | - | - | INIT |
Device B | - | - | - | - | INIT |
Device A | REQ | 7 | 0 | RESET, v0, maxRX:64, reason:1 | |
Device B | - | - | - | - | RESET_RECEIVED |
Device B | RSP | 0 | 0 | RESET, error: 0 | |
Device A | - | - | - | - | RESET_SENT |
Device B | REQ | 0 | 1 | RESET, v0, maxRX:64, reason:0 | |
Device A | - | - | - | - | RUNNING |
Device A | RSP | 1 | 1 | RESET, error: 0 | |
Device B | - | - | - | - | RUNNING |
Device B | ACK | 1 | 1 |
- A sends
RST_REQ_70
- B sends
RST_REQ_70
- A sends
RST_RSP_01
- B sends
RST_RSP_01
Details:
Device | Type | AFC | OFC | Payload Description | State |
---|---|---|---|---|---|
Device A | - | - | - | - | INIT |
Device B | - | - | - | - | INIT |
Device A | REQ | 7 | 0 | RESET, v0, maxRX:64, reason:1 | |
Device B | REQ | 7 | 0 | RESET, v0, maxRX:64, reason:0 | |
Device A | - | - | - | - | RESET_RECEIVED |
Device B | - | - | - | - | RESET_RECEIVED |
Device A | RSP | 0 | 1 | RESET, error: 0 | |
Device B | RSP | 0 | 1 | RESET, error: 0 | |
Device A | - | - | - | - | RUNNING |
Device B | - | - | - | - | RUNNING |
Device B | ACK | 1 | 1 | ||
Device B | ACK | 1 | 2 | ...data... | |
Device A | ACK | 2 | 1 |
- Device A sends
RST_REQ_70
- Device B sends
RST_RSP_00
- Device B sends
RST_REQ_01
- Device A CRASHES!
- Device A sends
RST_REQ_70
- Device B sends
RST_RSP_00
- Device B sends
RST_REQ_01
- Device A sends
RST_RSP_11
Details:
Device | Type | AFC | OFC | Payload Description | State |
---|---|---|---|---|---|
Device A | - | - | - | - | INIT |
Device B | - | - | - | - | INIT |
Device A | REQ | 7 | 0 | RESET, v0, maxRX:64, reason:1 | |
Device B | - | - | - | - | RESET_RECEIVED |
Device B | RSP | 0 | 0 | RESET, error: 0 | |
Device A | - | - | - | DEVICE A CRASHES AND RESTARTS | INIT |
Device B | REQ | 0 | 1 | RESET, v0, maxRX:64, reason:0 | |
Device A | - | - | - | Ignores previous packet because OFC was not zero | |
Device A | REQ | 7 | 0 | RESET, v0, maxRX:64, reason:1 | |
Device B | - | - | - | Resets itself, starting over | RESET_RECEIVED |
Device B | RSP | 0 | 0 | RESET, error: 0 | |
Device A | - | - | - | - | RESET_SENT |
Device B | REQ | 0 | 1 | RESET, v0, maxRX:64, reason:0 | |
Device A | - | - | - | - | RUNNING |
Device A | RSP | 1 | 1 | RESET, error: 0 | |
Device B | - | - | - | - | RUNNING |
Device B | ACK | 1 | 1 |