:TEP: 116
:Group: Core Working Group
:Type: Documentary
-:Status: Draft
-:TinyOS-Version: 2.x
+:Status: Final
+:TinyOS-Version: > 2.1
:Author: Philip Levis
-:Draft-Created: 10-Dec-2004
-:Draft-Version: $Revision$
-:Draft-Modified: $Date$
-:Draft-Discuss: TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu>
-
.. Note::
This memo documents a part of TinyOS for the TinyOS Community, and
command uint8_t payloadLength(message_t* msg);
command void setPayLoadLength(message_t* msg, uint8_t len);
command uint8_t maxPayloadLength();
- command void* getPayload(message_t* msg, uint8_t* len);
+ command void* getPayload(message_t* msg, uint8_t len);
}
A component can obtain a pointer to its data region within a packet by
-calling ``getPayload()`` the optional ``len`` argument is for also
-obtaining the size of the data region. A provider of a Packet
-interface MUST check if ``len`` is NULL and ignore it if it is. A
-component can also obtain the size of the data region with a call to
-``payloadLength``.
-
-A component can set the payload length with
-``setPayLoadLength.`` As Send interfaces always include a length
-parameter in their send call, this command is not required for
-sending, and so is never called in common use cases. Instead,
-it is a way for queues and other packet buffering components
-to store the full state of a packet without requiring additional
-memory allocation.
+calling ``getPayload()``. A call to this command includes the length
+the caller requires. The command ``maxPayloadLength`` returns the
+maximum length the payload can be: if the ``len`` parameter to
+``getPayload`` is greater than the value ``maxPayloadLength`` would
+return, ``getPayload`` MUST return NULL.
+
+
+A component can set the payload length with ``setPayLoadLength.`` A
+component can obtain the size of the data region of packet in use with
+a call to ``payloadLength``. As Send interfaces always include a
+length parameter in their send call, ``setPayLoadLength`` is not
+required for sending, and so is never called in common use
+cases. Instead, it is a way for queues and other packet buffering
+components to store the full state of a packet without requiring
+additional memory allocation.
The distinction between ``payloadLength`` and ``maxPayloadLength``
-comes from whether the packet is being received or sent. In the receive
-case, determining the size of the existing data payload is needed;
-in the send case, a component needs to know how much data it can put
-in the packet.
-
-The Packet interface assumes that headers have a fixed size.
-It is difficult to return a pointer into the data region when its
-position will only be known once the header values are bound.
-
-Generally, an incoming call to the Packet interface of a protocol
-has an accompanying outgoing call to the Packet interface of the
-component below it. The one exception to this is the data link
-layer. For example, if there is a network that introduces
-16-bit sequence numbers to packets, it might look like this::
+comes from whether the packet is being received or sent. In the
+receive case, determining the size of the existing data payload is
+needed; in the send case, a component needs to know how much data it
+can put in the packet. By definition, the return value of
+``payloadLength`` must be less than or equal to the return value of
+``maxPayloadLength``.
+
+The Packet interface assumes that headers have a fixed size. It is
+difficult to return a pointer into the data region when its position
+will only be known once the header values are bound.
+
+The ``clear`` command clears out all headers, footers, and metadata
+for lower layers. For example, calling ``clear`` on a routing
+component, such as CollectionSenderC[4]_, will clear out the
+collection headers and footers. Furthermore, CollectionSenderC will
+recursively call ``clear`` on the layer below it, clearing out the
+link layer headers and footers. Calling ``clear`` is typically
+necessary when moving a packet across two link layers. Otherwise, the
+destination link layer may incorrectly interpret metadata from the
+source link layer, and, for example, transmit the packet on the wrong
+RF channel. Because ``clear`` prepares a packet for a particular link
+layer, in this example correct code would call the command on the
+destination link layer, not the source link layer.
+
+Typically, an incoming call to the Packet interface of a protocol has
+an accompanying outgoing call to the Packet interface of the component
+below it. The one exception to this is the data link layer. For
+example, if there is a network that introduces 16-bit sequence numbers
+to packets, it might look like this::
generic module SequenceNumber {
provides interface Packet;
};
command void Packet.clear(message_t* msg) {
- uint8_t len;
- void* payload = call SubPacket.getPayload(msg, &len);
- memset(payload, len, 0);
+ void* payload = call SubPacket.getPayload(msg, call SubPacket.maxPayloadLength());
+ call SubPacket.clear();
+ if (payload != NULL) {
+ memset(payload, sizeof(seq_header_t), 0);
+ }
}
command uint8_t Packet.payloadLength(message_t* msg) {
return SubPacket.maxPayloadLength(msg) - SEQNO_OFFSET;
}
- command void* Packet.getPayload(message_t* msg, uint8_t* len) {
- uint8_t* payload = call SubPacket.getPayload(msg, len);
- if (len != NULL) {
- *len -= SEQNO_OFFSET;
+ command void* Packet.getPayload(message_t* msg, uint8_t len) {
+ uint8_t* payload = call SubPacket.getPayload(msg, len + SEQNO_OFFSET);
+ if (payload != NULL) {
+ payload += SEQNO_OFFSET;
}
- return payload + SEQNO_OFFSET;
+ return payload;
}
}
interface AMPacket {
command am_addr_t address();
command am_addr_t destination(message_t* amsg);
+ command am_addr_t source(message_t* amsg);
command void setDestination(message_t* amsg, am_addr_t addr);
+ command void setSource(message_t* amsg, am_addr_t addr);
command bool isForMe(message_t* amsg);
command am_id_t type(message_t* amsg);
command void setType(message_t* amsg, am_id_t t);
+ command am_group_t group(message_t* amsg);
+ command void setGroup(message_t* amsg, am_group_t grp);
+ command am_group_t localGroup();
}
The command address() returns the local AM address of the
-node. AMPacket provides accessors for its two fields, destination and
-type. It also provides commands to set these fields, for the same
-reason that Packet allows a caller to set the payload length.
-Packet interfaces SHOULD provide accessors
-and mutators for all of their fields to enable queues and other
-buffering to store values in a packet buffer. Typically, a component
-stores these values in the packet buffer itself (where the field is),
-but when necessary it may use the metadata region of message_t or other
-locations.
+node. AMPacket provides accessors for its four fields, destination,
+source, type and group. It also provides commands to set these
+fields, for the same
+reason that Packet allows a caller to set the payload length. Packet
+interfaces SHOULD provide accessors and mutators for all of their
+fields to enable queues and other buffering to store values in a
+packet buffer. Typically, a component stores these values in the
+packet buffer itself (where the field is), but when necessary it may
+use the metadata region of message_t or other locations.
+
+The group field refers to the AM group, a logical network identifier.
+Link layers will typically only signal reception for packets whose AM
+group matches the node's, which ``localGroup`` returns.
2.2 Sending interfaces
--------------------------------------------------------------------
event void sendDone(message_t* msg, error_t error);
command uint8_t maxPayloadLength();
- command void* getPayload(message_t* msg);
+ command void* getPayload(message_t* msg, uint8_t len);
}
while this is the AMSend interface::
event void sendDone(message_t* msg, error_t error);
command uint8_t maxPayloadLength();
- command void* getPayload(message_t* msg);
+ command void* getPayload(message_t* msg, uint8_t len);
}
Sending interfaces MUST include these four commands and one event.
The duplication of some of the commands in Packet is solely for ease
of use: ``maxPayloadLength`` and ``getPayload`` MUST behave
-identically as ``Packet.maxPayloadLength`` and ``Packet.getPayload``,
-with the exception that the latter has no length parameter (it should
-behave as if the length parameter of the ``Packet`` call were
-NULL). Their inclusion is so that components do not have to wire to
+identically as ``Packet.maxPayloadLength`` and ``Packet.getPayload.``
+Their inclusion is so that components do not have to wire to
both Packet and the sending interface for basic use cases.
When called with a length that is too long for the underlying
a new sending interface that supports multiple pending transmissions.
The cancel command allows a sender to cancel the current transmission.
-A call to cancel when there is no pending sendDone event MUST return FAIL.
-If there is a pending sendDone event and the cancel returns SUCCESS, then
-the packet layer MUST NOT transmit the packet and MUST signal sendDone
-with ECANCEL as its error code. If there is a pending sendDone event
-and cancel returns FAIL, then sendDone SHOULD occur as if the cancel
-was not called.
+A call to cancel when there is no pending sendDone event MUST return
+FAIL. If there is a pending sendDone event and the cancel returns
+SUCCESS, then the packet layer MUST NOT transmit the packet and MUST
+signal sendDone with ECANCEL as its error code. If there is a pending
+sendDone event and cancel returns FAIL, then sendDone MUST occur as if
+the cancel was not called.
2.3 Receive interface
--------------------------------------------------------------------
interface Receive {
event message_t* receive(message_t* msg, void* payload, uint8_t len);
- command void* getPayload(message_t* msg, uint8_t* len);
- command uint8_t payloadLength(message_t* msg);
}
-A call to ``Receive.getPayload()`` MUST behave identically to a call
-to ``Packet.getPayload()``. The ``receive()`` event's ``payload``
-parameter MUST be identical to what a call to ``getPayload()`` would
-return, and the ``len`` parameter MUST be identical to the length that
-a call to ``getPayload`` would return. These parameters are for
+The ``receive()`` event's ``payload`` parameter MUST be identical to
+what a call to the corresponding ``Packet.getPayload()`` would return,
+and the ``len`` parameter MUST be identical to the length that a call
+to ``Packet.getPayload`` would return. These parameters are for
convenience, as they are commonly used by receive handlers, and their
-presence removes the need for a call to ``getPayload()``, while
-``getPayload()`` is a convenience so a component does not have to wire
-to ``Packet.`` The command ``payloadLength`` has a similar motivation
-and the same semantics as its twin in ``Packet``.
-
-Receive has a *buffer-swap* policy. The handler of the event MUST return
-a pointer to a valid message buffer for the signaler to use. This
-approach enforces an equilibrium between upper and lower packet
-layers. If an upper layer cannot handle packets as quickly as they
-are arriving, it still has to return a valid buffer to the lower
+presence removes the need for a call to ``getPayload()``. Unlike Send,
+Receive does not have a convenience ``getPayload`` call, because doing
+so prevents fan-in. As Receive has only a single event, users of
+Receive can be wired multiple times.
+
+Receive has a *buffer-swap* policy. The handler of the event MUST
+return a pointer to a valid message buffer for the signaler to
+use. This approach enforces an equilibrium between upper and lower
+packet layers. If an upper layer cannot handle packets as quickly as
+they are arriving, it still has to return a valid buffer to the lower
layer. This buffer could be the ``msg`` parameter passed to it: it
just returns the buffer it was given without looking at it. Following
-this policy means that a data-rate mismatch in an upper-level component
-will be isolated to that component. It will drop packets, but it will
-not prevent other components from receiving packets. If an upper
-layer did not have to return a buffer immediately, then when an
+this policy means that a data-rate mismatch in an upper-level
+component will be isolated to that component. It will drop packets,
+but it will not prevent other components from receiving packets. If an
+upper layer did not have to return a buffer immediately, then when an
upper layer cannot handle packets quickly enough it will end up
holding all of them, starving lower layers and possibly preventing
packet reception.
.. [4] TEP 113: Serial Communication.
-
-
-