]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - doc/html/tep116.html
TEP 116 is finalized.
[tinyos-2.x.git] / doc / html / tep116.html
index 68a5c269ff791dbc0ed457b5123b398b559444f5..b89fc6508a162ece3ba2777aeed2f319bd22e232 100644 (file)
@@ -3,7 +3,7 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<meta name="generator" content="Docutils 0.4.1: http://docutils.sourceforge.net/" />
 <title>Packet Protocols</title>
 <meta name="author" content="Philip Levis" />
 <style type="text/css">
@@ -41,11 +41,6 @@ blockquote.epigraph {
 dd {
   margin-bottom: 0.5em }
 
-/* Uncomment (& remove this text!) to get bold-faced definition list terms
-dt {
-  font-weight: bold }
-*/
-
 div.abstract {
   margin: 2em 5em }
 
@@ -296,19 +291,11 @@ ul.auto-toc {
 <tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
 </tr>
 <tr><th class="docinfo-name">Status:</th>
-<td>Draft</td></tr>
-<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
+<td>Final</td></tr>
+<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">&gt; 2.1</td>
 </tr>
 <tr><th class="docinfo-name">Author:</th>
 <td>Philip Levis</td></tr>
-<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">10-Dec-2004</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.6</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2007-02-28</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List &lt;tinyos-devel at mail.millennium.berkeley.edu&gt;</td>
-</tr>
 </tbody>
 </table>
 <div class="note">
@@ -384,7 +371,10 @@ HIL.</p>
 <em>Packet</em> interfaces are for accessing message fields and payloads.
 <em>Send</em> interfaces are for transmitting packets, and are
 distinguished by their addressing scheme.
-Finally, the <em>Receive</em> interface is for handling packet reception events.</p>
+The <em>Receive</em> interface is for handling packet reception events.
+Finally, depending on whether the protocol has a dispatch identifier
+field, the Receive and Send interfaces may be parameterized in order
+to support multiple higher-level clients.</p>
 <div class="section">
 <h2><a id="packet-interfaces" name="packet-interfaces">2.1 Packet interfaces</a></h2>
 <p>The basic TinyOS 2.x message buffer type is message_t, which is
@@ -406,35 +396,50 @@ interface Packet {
   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);
 }
 </pre>
 <p>A component can obtain a pointer to its data region within a packet by
-calling <tt class="docutils literal"><span class="pre">getPayload()</span></tt> the optional <tt class="docutils literal"><span class="pre">len</span></tt> argument is for also
-obtaining the size of the data region. A provider of a Packet
-interface MUST check if <tt class="docutils literal"><span class="pre">len</span></tt> is NULL and ignore it if it is. A
-component can also obtain the size of the data region with a call to
-<tt class="docutils literal"><span class="pre">payloadLength</span></tt>.</p>
-<p>A component can set the payload length with
-<tt class="docutils literal"><span class="pre">setPayLoadLength.</span></tt> 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.</p>
+calling <tt class="docutils literal"><span class="pre">getPayload()</span></tt>. A call to this command includes the length
+the caller requires. The command <tt class="docutils literal"><span class="pre">maxPayloadLength</span></tt> returns the
+maximum length the payload can be: if the <tt class="docutils literal"><span class="pre">len</span></tt> parameter to
+<tt class="docutils literal"><span class="pre">getPayload</span></tt> is greater than the value <tt class="docutils literal"><span class="pre">maxPayloadLength</span></tt> would
+return, <tt class="docutils literal"><span class="pre">getPayload</span></tt> MUST return NULL.</p>
+<p>A component can set the payload length with <tt class="docutils literal"><span class="pre">setPayLoadLength.</span></tt> A
+component can obtain the size of the data region of packet in use with
+a call to <tt class="docutils literal"><span class="pre">payloadLength</span></tt>. As Send interfaces always include a
+length parameter in their send call, <tt class="docutils literal"><span class="pre">setPayLoadLength</span></tt> 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.</p>
 <p>The distinction between <tt class="docutils literal"><span class="pre">payloadLength</span></tt> and <tt class="docutils literal"><span class="pre">maxPayloadLength</span></tt>
-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.</p>
-<p>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.</p>
-<p>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:</p>
+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
+<tt class="docutils literal"><span class="pre">payloadLength</span></tt> must be less than or equal to the return value of
+<tt class="docutils literal"><span class="pre">maxPayloadLength</span></tt>.</p>
+<p>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.</p>
+<p>The <tt class="docutils literal"><span class="pre">clear</span></tt> command clears out all headers, footers, and metadata
+for lower layers. For example, calling <tt class="docutils literal"><span class="pre">clear</span></tt> on a routing
+component, such as CollectionSenderC[4]_, will clear out the
+collection headers and footers. Furthermore, CollectionSenderC will
+recursively call <tt class="docutils literal"><span class="pre">clear</span></tt> on the layer below it, clearing out the
+link layer headers and footers. Calling <tt class="docutils literal"><span class="pre">clear</span></tt> 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 <tt class="docutils literal"><span class="pre">clear</span></tt> 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.</p>
+<p>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:</p>
 <pre class="literal-block">
 generic module SequenceNumber {
   provides interface Packet;
@@ -450,9 +455,11 @@ implementation {
   };
 
   command void Packet.clear(message_t* msg) {
-    uint8_t len;
-    void* payload = call SubPacket.getPayload(msg, &amp;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) {
@@ -467,12 +474,12 @@ implementation {
     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;
   }
 }
 </pre>
@@ -498,16 +505,30 @@ has this signature:</p>
 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();
 }
 </pre>
 <p>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.</p>
+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.</p>
+<p>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 <tt class="docutils literal"><span class="pre">localGroup</span></tt> returns.</p>
 </div>
 <div class="section">
 <h2><a id="sending-interfaces" name="sending-interfaces">2.2 Sending interfaces</a></h2>
@@ -524,7 +545,7 @@ interface Send {
   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);
 }
 </pre>
 <p>while this is the AMSend interface:</p>
@@ -535,17 +556,38 @@ interface AMSend {
   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);
 }
 </pre>
 <p>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: <tt class="docutils literal"><span class="pre">maxPayloadLength</span></tt> and <tt class="docutils literal"><span class="pre">getPayload</span></tt> MUST behave
-identically as <tt class="docutils literal"><span class="pre">Packet.maxPayloadLength</span></tt> and <tt class="docutils literal"><span class="pre">Packet.getPayload</span></tt>,
-with the exception that the latter has no length parameter (it should
-behave as if the length parameter of the <tt class="docutils literal"><span class="pre">Packet</span></tt> call were
-NULL). Their inclusion is so that components do not have to wire to
+identically as <tt class="docutils literal"><span class="pre">Packet.maxPayloadLength</span></tt> and <tt class="docutils literal"><span class="pre">Packet.getPayload.</span></tt>
+Their inclusion is so that components do not have to wire to
 both Packet and the sending interface for basic use cases.</p>
+<p>When called with a length that is too long for the underlying
+maximum transfer unit (MTU), the send command MUST return ESIZE.</p>
+<p>The <tt class="docutils literal"><span class="pre">Send</span></tt> and <tt class="docutils literal"><span class="pre">AMSend</span></tt> interfaces have an explicit queue of
+depth one. A call to <tt class="docutils literal"><span class="pre">send</span></tt> on either of these interfaces MUST
+return EBUSY if a prior call to <tt class="docutils literal"><span class="pre">send</span></tt> returned SUCCESS but no
+<tt class="docutils literal"><span class="pre">sendDone</span></tt> event has been signaled yet. More explicitly:</p>
+<pre class="literal-block">
+if (call Send.send(...) == SUCCESS &amp;&amp;
+    call Send.send(...) == SUCCESS) {
+   // This block is unreachable.
+}
+</pre>
+<p>Systems that need send queues have two options. They can
+use a QueueC (found in tos/system) to store pending packet pointers
+and serialize them onto sending interface, or they can introduce
+a new sending interface that supports multiple pending transmissions.</p>
+<p>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 MUST occur as if
+the cancel was not called.</p>
 </div>
 <div class="section">
 <h2><a id="receive-interface" name="receive-interface">2.3 Receive interface</a></h2>
@@ -553,41 +595,40 @@ both Packet and the sending interface for basic use cases.</p>
 <pre class="literal-block">
 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);
 }
 </pre>
-<p>A call to <tt class="docutils literal"><span class="pre">Receive.getPayload()</span></tt> MUST behave identically to a call
-to <tt class="docutils literal"><span class="pre">Packet.getPayload()</span></tt>. The <tt class="docutils literal"><span class="pre">receive()</span></tt> event's <tt class="docutils literal"><span class="pre">payload</span></tt>
-parameter MUST be identical to what a call to <tt class="docutils literal"><span class="pre">getPayload()</span></tt> would
-return, and the <tt class="docutils literal"><span class="pre">len</span></tt> parameter MUST be identical to the length that
-a call to <tt class="docutils literal"><span class="pre">getPayload</span></tt> would return. These parameters are for
+<p>The <tt class="docutils literal"><span class="pre">receive()</span></tt> event's <tt class="docutils literal"><span class="pre">payload</span></tt> parameter MUST be identical to
+what a call to the corresponding <tt class="docutils literal"><span class="pre">Packet.getPayload()</span></tt> would return,
+and the <tt class="docutils literal"><span class="pre">len</span></tt> parameter MUST be identical to the length that a call
+to <tt class="docutils literal"><span class="pre">Packet.getPayload</span></tt> 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 <tt class="docutils literal"><span class="pre">getPayload()</span></tt>, while
-<tt class="docutils literal"><span class="pre">getPayload()</span></tt> is a convenience so a component does not have to wire
-to <tt class="docutils literal"><span class="pre">Packet.</span></tt> The command <tt class="docutils literal"><span class="pre">payloadLength</span></tt> has a similar motivation
-and the same semantics as its twin in <tt class="docutils literal"><span class="pre">Packet</span></tt>.</p>
-<p>Receive has a <em>buffer-swap</em> 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 <tt class="docutils literal"><span class="pre">getPayload()</span></tt>. Unlike Send,
+Receive does not have a convenience <tt class="docutils literal"><span class="pre">getPayload</span></tt> call, because doing
+so prevents fan-in. As Receive has only a single event, users of
+Receive can be wired multiple times.</p>
+<p>Receive has a <em>buffer-swap</em> 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 <tt class="docutils literal"><span class="pre">msg</span></tt> 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.</p>
 <p>A <em>user</em> of the Receive interface has three basic options when it
 handles a receive event:</p>
+<blockquote>
 <ol class="arabic simple">
 <li>Return <tt class="docutils literal"><span class="pre">msg</span></tt> without touching it.</li>
 <li>Copy some data out of <tt class="docutils literal"><span class="pre">payload</span></tt> and return <tt class="docutils literal"><span class="pre">msg</span></tt>.</li>
 <li>Store <tt class="docutils literal"><span class="pre">msg</span></tt> in its local frame and return a different <tt class="docutils literal"><span class="pre">message_t*</span></tt> for the lower layer to use.</li>
 </ol>
+</blockquote>
 <p>These are simple code examples of the three cases:</p>
 <pre class="literal-block">
 // Case 1
@@ -623,8 +664,8 @@ the signaling of <tt class="docutils literal"><span class="pre">receive.</span><
 <div class="section">
 <h2><a id="dispatch" name="dispatch">2.4 Dispatch</a></h2>
 <p>A packet protocol MAY have a dispatch identifier. This generally manifests
-as the protocol component provided parameterized interfaces (rather than
-a single interface instances). A dispatch identifier allows multiple
+as the protocol component providing parameterized interfaces (rather than
+a single interface instance). A dispatch identifier allows multiple
 services to use a protocol independently. If a protocol provides a
 dispatch mechanism, then each dispatch identifier SHOULD correspond to
 a single packet format: if an identifier corresponds to multiple packet
@@ -753,7 +794,7 @@ a certain am_id_t MUST NOT instantiate another AMSnoopingReceiverC,
 AMSnooperC, or AMReceiverC with the same am_id_t.</p>
 </div>
 <div class="section">
-<h2><a id="amsender" name="amsender">4.5 AMSender</a></h2>
+<h2><a id="amsenderc" name="amsenderc">4.5 AMSenderC</a></h2>
 <p>AMSenderC has the following signature:</p>
 <pre class="literal-block">
 generic configuration AMSenderC(am_id_t AMId) {
@@ -773,8 +814,13 @@ but it MUST be fair, where fair means that each client with outstanding
 packets receives a reasonable approximation of an equal share of the
 available transmission bandwidth.</p>
 </div>
+</div>
+<div class="section">
+<h1><a id="power-management-and-local-address" name="power-management-and-local-address">5. Power Management and Local Address</a></h1>
+<p>In addition to standard datapath interfaces for sending and
+receiving packets, an active message layer also has control interfaces.</p>
 <div class="section">
-<h2><a id="power-management" name="power-management">4.6 Power Management</a></h2>
+<h2><a id="power-management" name="power-management">5.1 Power Management</a></h2>
 <p>The communication virtualizations do not support power management.
 ActiveMessageC provides SplitControl for explicit power control.
 For packet communication to operate properly, a component in an
@@ -783,6 +829,17 @@ The HAL underneath ActiveMessageC  MAY employ power management
 techniques, such as TDMA scheduling or low power listening, when
 &quot;on.&quot;</p>
 </div>
+<div class="section">
+<h2><a id="local-active-message-address" name="local-active-message-address">5.2 Local Active Message Address</a></h2>
+<p>An application can change ActiveMessageC's local AM address
+at runtime. This will change which packets a node receives and
+the source address it embeds in packets. To change the local AM
+address at runtime, a component can wire to the component
+<tt class="docutils literal"><span class="pre">ActiveMessageAddressC</span></tt>. This component only changes the
+AM address of the default radio stack (AMSenderC, etc.); if
+a radio has multiple stacks those may have other components
+for changing their addresses in a stack-specific fashion.</p>
+</div>
 </div>
 <div class="section">
 <h1><a id="hal-requirements" name="hal-requirements">5. HAL Requirements</a></h1>