]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - doc/html/tep116.html
Merge devel code into the trunk.
[tinyos-2.x.git] / doc / html / tep116.html
diff --git a/doc/html/tep116.html b/doc/html/tep116.html
new file mode 100644 (file)
index 0000000..f017163
--- /dev/null
@@ -0,0 +1,921 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<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/" />
+<title>Packet Protocols</title>
+<meta name="author" content="Philip Levis" />
+<style type="text/css">
+
+/*
+:Author: David Goodger
+:Contact: goodger@users.sourceforge.net
+:date: $Date$
+:version: $Revision$
+:copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+*/
+body {
+  font-family: Times;
+  font-size: 16px;
+}
+
+.first {
+  margin-top: 0 ! important }
+
+.last {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+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 }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.attention, div.caution, div.danger, div.error, div.hint,
+div.important, div.note, div.tip, div.warning, div.admonition {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.hint p.admonition-title, div.important p.admonition-title,
+div.note p.admonition-title, div.tip p.admonition-title,
+div.admonition p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em }
+
+div.footer, div.header {
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin-left: 1em ;
+  border: medium outset ;
+  padding: 0em 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1 {
+  font-family: Arial, sans-serif;
+  font-size: 20px;
+}
+
+h1.title {
+ text-align: center;
+ font-size: 32px;
+}
+
+h2 {
+ font-size: 16px;
+ font-family: Arial, sans-serif;
+}
+
+h2.subtitle {
+  text-align: center }
+
+h3 {
+ font-size: 12px;
+ font-family: Arial, sans-serif;
+}
+
+hr {
+  width: 75% }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font-family: serif ;
+  font-size: 100% }
+
+pre.line-block {
+  font-family: serif ;
+  font-size: 100% }
+
+pre.literal-block, pre.doctest-block {
+  margin-left: 2em ;
+  margin-right: 2em ;
+  background-color: #eeeeee;
+  border-color: #000000;
+  border-width: thin; 
+  font-size: 14px
+}
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.option-argument {
+  font-style: italic }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+table {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.citation {
+  border-left: solid thin gray ;
+  padding-left: 0.5ex }
+
+table.docinfo {
+  margin: 2em 4em;
+}
+
+table.footnote {
+  border-left: solid thin black ;
+  padding-left: 0.5ex }
+
+td, th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+th.docinfo-name, th.field-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap;
+  }
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+  font-size: 100% }
+
+tt {}
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="packet-protocols">
+<h1 class="title">Packet Protocols</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr class="field"><th class="docinfo-name">TEP:</th><td class="field-body">116</td>
+</tr>
+<tr class="field"><th class="docinfo-name">Group:</th><td class="field-body">Core Working Group</td>
+</tr>
+<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>
+</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.1.2.10</td>
+</tr>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-06-22</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">
+<p class="first admonition-title">Note</p>
+<p class="last">This memo documents a part of TinyOS for the TinyOS Community, and
+requests discussion and suggestions for improvements.  Distribution
+of this memo is unlimited. This memo is in full compliance with
+TEP 1.</p>
+</div>
+<div class="section">
+<h1><a id="abstract" name="abstract">Abstract</a></h1>
+<p>The memo documents the interfaces used by packet protocol components in
+TinyOS 2.x as well as the structure and implementation of ActiveMessageC,
+the basic data-link HIL component. It also documents the virtualized
+active message interfaces AMSender and AMReceiver.</p>
+</div>
+<div class="section">
+<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
+<p>Sensor nodes are network-centric devices. Much of their software
+complexity comes from network protocols and their interactions.
+In TinyOS, the basic network abstraction is an <em>active message</em>,
+a single-hop, unreliable packet. Active messages have a destination
+address, provide synchronous acknowledgements, and can be of
+variable length up to a fixed maximum size. They also have a
+type field, which is essentially a protocol identifier for
+components built on top of this abstraction.</p>
+<p>In TinyOS 1.x, the component GenericComm provides interfaces for
+transmitting and receiving active messages:</p>
+<pre class="literal-block">
+configuration GenericComm {
+  provides {
+    interface StdControl as Control;
+    interface SendMsg[uint8_t id];
+    interface ReceiveMsg[uint8_t id];
+    command uint16_t activity();
+  }
+  uses {
+    event result_t sendDone();
+  }
+}
+</pre>
+<p>This component, while simple, has several issues. First, it has the
+activity() commmand, which does not have a single caller in the entire
+TinyOS tree. This command requires GenericComm to allocate a
+timer, wasting CPU cycles and RAM.</p>
+<p>Second, it does not allow a node to receive packets besides
+those destined to it.  Several network
+protocols (e.g., MintRoute <a class="footnote-reference" href="#id6" id="id1" name="id1">[1]</a>, TAG <a class="footnote-reference" href="#id7" id="id2" name="id2">[2]</a>) take advantage
+of snooping on these packets for a variety of improvements in efficiency or
+performance. This has led to the creation of GenericCommPromiscuous,
+whose Receive interface does not distinguish
+between packets received that were addressed to the node and
+packets received that were addressed to other nodes. Choosing
+one of the two implementations is a global decision across
+an application. There is a way to enable both reception
+semantics at the same time for a different protocols,
+but they require a creative use of default event handlers.</p>
+<p>Third, it assumes that components will directly access the packet
+structure, the accepted approach in TinyOS 1.x. However, directly
+accessing packet structures introduces unforseen dependencies:
+a component that names a header field, for example, binds itself
+to data link layers that have a field with that name. Similarly,
+components on top of GenericComm directly access the data payload
+of a packet.</p>
+<p>TEP 111 documents the structure of a TinyOS 2.x packet buffer <a class="footnote-reference" href="#id8" id="id3" name="id3">[3]</a>.
+This TEP documents the interfaces used to access packet buffers,
+as well as ActiveMessageC, the basic data-link packet communication
+HIL.</p>
+</div>
+<div class="section">
+<h1><a id="communication-interfaces" name="communication-interfaces">2. Communication interfaces</a></h1>
+<p>Packet-level communication has three basic classes of interfaces.
+<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>
+<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
+described in TEP 111. message_t right-justifies data-link
+headers to the data payload so that higher-level components can
+pass buffers between different data link layers without having
+to move data payloads. This means that the data payload of a
+data link frame is always at a fixed offset of a message_t.</p>
+<p>Once protocols layer on top of each other, the data
+payload for components on top of the data link layer are
+no longer at a fixed offset. Where a component can put its
+header or data depends on what headers underlying components
+introduce. Therefore, in order to be able to find out where
+it can put its data, it must query the components below it.
+The Packet interface defines this mechanism:</p>
+<pre class="literal-block">
+interface Packet {
+  command void clear(message_t* msg);
+  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);
+}
+</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>
+<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>
+<pre class="literal-block">
+generic module SequenceNumber {
+  provides interface Packet;
+  uses interface Packet as SubPacket;
+}
+implementation {
+  typedef nx_struct seq_header {
+    nx_uint16_t seqNo;
+  } seq_header_t;
+
+  enum {
+    SEQNO_OFFSET = sizeof(seq_header_t),
+  };
+
+  command void Packet.clear(message_t* msg) {
+    uint8_t len;
+    void* payload = call SubPacket.getPayload(msg, &amp;len);
+    memset(payload, len, 0);
+  }
+
+  command uint8_t Packet.payloadLength(message_t* msg) {
+    return SubPacket.payloadLength(msg) - SEQNO_OFFSET;
+  }
+
+  command void Packet.setPayloadLength(message_t* msg, uint8_t len) {
+    SubPacket.setPayloadLength(msg, len + SEQNO_OFFSET);
+  }
+
+  command uint8_t Packet.maxPayloadLength() {
+    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;
+    }
+    return payload + SEQNO_OFFSET;
+  }
+}
+</pre>
+<p>The above example is incomplete: it does not include the code for
+the send path that increments sequence numbers.</p>
+<p>In practice, calls to Packet are very efficient even if they
+pass through many components before reaching the data link
+layer. nesC's inlining means that in almost all cases
+there will not actually be any function calls, and since payload
+position and length calculations all use constant offsets,
+the compiler generally uses constant folding to generate a
+fixed offset.</p>
+<p>The Packet interface provides access to the one field all packet
+layers have, the data payload. Communication layers can add additional
+header and footer fields, and may need to provide access to these
+fields. If a packet communication component provides access to header
+and/or footer fields, it MUST do so through an interface. The interface
+SHOULD have a name of the form <em>XPacket</em>, where <em>X</em> is a name that
+describes the communication layer. For example, active message components
+provide both the Packet interface and the AMPacket interface. The latter
+has this signature:</p>
+<pre class="literal-block">
+interface AMPacket {
+  command am_addr_t address();
+  command am_addr_t destination(message_t* amsg);
+  command void setDestination(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);
+}
+</pre>
+<p>The command address() returns the local AM address of the
+node. AMPacket provides accessors for its two fields, destination and
+type. It does not provide commands to set these fields, as they are
+set in the sending call path (see Section 2.3). The <tt class="docutils literal"><span class="pre">setDestination</span></tt>
+and <tt class="docutils literal"><span class="pre">setType</span></tt> commands fulfill a similar purpose to
+<tt class="docutils literal"><span class="pre">Packet.setLength</span></tt>.</p>
+</div>
+<div class="section">
+<h2><a id="sending-interfaces" name="sending-interfaces">2.2 Sending interfaces</a></h2>
+<p>There are multiple sending interfaces, corresponding to different
+addressing modes. For example, address-free protocols, such as
+collection routing, provide the basic <tt class="docutils literal"><span class="pre">Send</span></tt> interface. Active
+message communication has a destination of an AM address, so
+it provides the <tt class="docutils literal"><span class="pre">AMSend</span></tt> interface.  This, for example, is the
+basic, address-free Send interface:</p>
+<pre class="literal-block">
+interface Send {
+  command error_t send(message_t* msg, uint8_t len);
+  command error_t cancel(message_t* msg);
+  event void sendDone(message_t* msg, error_t error);
+
+  command uint8_t maxPayloadLength();
+  command void* getPayload(message_t* msg);
+}
+</pre>
+<p>while this is the AMSend interface:</p>
+<pre class="literal-block">
+interface AMSend {
+  command error_t send(am_addr_t addr, message_t* msg, uint8_t len);
+  command error_t cancel(message_t* msg);
+  event void sendDone(message_t* msg, error_t error);
+
+  command uint8_t maxPayloadLength();
+  command void* getPayload(message_t* msg);
+}
+</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
+both Packet and the sending interface for basic use cases.</p>
+</div>
+<div class="section">
+<h2><a id="receive-interface" name="receive-interface">2.3 Receive interface</a></h2>
+<p>Receive is the interface for receiving packets. It has this signature:</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
+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
+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
+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>
+<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>
+<p>These are simple code examples of the three cases:</p>
+<pre class="literal-block">
+// Case 1
+message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) {
+  return msg;
+}
+
+// Case 2
+uint16_t value;
+message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) {
+  if (len &gt;= sizeof(uint16_t)) {
+    nx_uint16_t* nval = (nx_uint16_t*)payload;
+    value = *nval;
+  }
+  return msg;
+}
+
+//Case 3
+message_t* ptr;
+message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) {
+  message_t* tmp = ptr;
+  ptr = msg;
+  post processTask();
+  return tmp;
+}
+</pre>
+<p>Because of case 3), a lower layer MUST respect the buffer swap semantics
+and use the pointer returned from <tt class="docutils literal"><span class="pre">receive</span></tt>. The pointer passed as
+a parameter to <tt class="docutils literal"><span class="pre">receive</span></tt> MUST NOT be touched, used, or stored after
+the signaling of <tt class="docutils literal"><span class="pre">receive.</span></tt></p>
+</div>
+<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
+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
+formats, then there is no way to disambiguate them. Packets whose internal
+structure depends on their fields (for example,
+a packet that has a control field which indicates which optional fields
+are present) do not pose such problems.</p>
+</div>
+</div>
+<div class="section">
+<h1><a id="hil-activemessagec" name="hil-activemessagec">3. HIL: ActiveMessageC</a></h1>
+<p>A platform MUST provide ActiveMessageC as a basic HIL to
+packet-level communication.  ActiveMessageC provides a best-effort,
+single-hop communication abstraction.  Every active message has a
+16-bit destination address and an 8-bit type. There is one reserved
+destination address, <tt class="docutils literal"><span class="pre">AM_BROADCAST_ADDR</span></tt>, which has the value
+of <tt class="docutils literal"><span class="pre">0xffff</span></tt>. ActiveMessageC has the following signature:</p>
+<pre class="literal-block">
+configuration ActiveMessageC {
+  provides {
+    interface Init;
+    interface SplitControl;
+
+    interface AMSend[uint8_t id];
+    interface Receive[uint8_t id];
+    interface Receive as Snoop[uint8_t id];
+
+    interface Packet;
+    interface AMPacket;
+    interface PacketAcknowledgements;
+  }
+}
+</pre>
+<p>The Receive interface is for packets destined to the node, while
+the Snoop interface is for packets destined to other nodes. A
+packet is destined for a node if its destination AM address is
+either the AM broadcast address or an address associated with
+the AM stack. Different link layers have different snooping
+capabilities. The Snoop interface does not assume always-on
+listening, for example, in the case of a TDMA or RTS/CTS data
+link layer. By separating out these two interfaces, ActiveMessageC
+avoids the complications encountered in 1.x with regards to
+GenericComm vs. GenericCommPromiscuous.</p>
+<p>ActiveMessageC is usually just a configuration that has
+pass-through wiring to a chip-specific HAL active message
+implementation. The definition of ActiveMessageC is left
+to the platform for when a node has more than one
+radio. In this case, the platform decides how to map the
+basic packet abstraction to the hardware underneath. Approaches
+include choosing one radio or having some form of address-based
+dispatch.</p>
+</div>
+<div class="section">
+<h1><a id="am-services-amsenderc-amreceiverc-amsnooperc-amsnoopingreceiverc" name="am-services-amsenderc-amreceiverc-amsnooperc-amsnoopingreceiverc">4. AM Services: AMSenderC, AMReceiverC, AMSnooperC, AMSnoopingReceiverC</a></h1>
+<p>TinyOS 2.x provides four component single-hop communication
+virtualizations to applications:
+AMReceiverC, AMSnooperC, AMSnoopingReceiverC, and AMSenderC. Each is a
+generic component that takes an active message ID as a
+parameter. These components assume the existence of ActiveMessageC.</p>
+<div class="section">
+<h2><a id="dispatch-am-id-t" name="dispatch-am-id-t">4.1 Dispatch: <tt class="docutils literal"><span class="pre">am_id_t</span></tt></a></h2>
+<p>Active messages have an 8-bit type field, which allows multiple
+protocols to all use AM communication without conflicting. Following
+the guidelines for protocol dispatch identifiers, each
+am_id_t used in a network SHOULD have a single packet format, so
+that the am_id_t, combined with the packet contents, are sufficient
+to determine the exact packet format.</p>
+</div>
+<div class="section">
+<h2><a id="amreceiverc" name="amreceiverc">4.2 AMReceiverC</a></h2>
+<p>AMReceiverC has the following signature:</p>
+<pre class="literal-block">
+generic configuration AMReceiverC(am_id_t t) {
+  provides{
+    interface Receive;
+    interface Packet;
+    interface AMPacket;
+  }
+}
+</pre>
+<p>AMReceiver.Receive.receive is signalled whenever the packet layer
+receives an active message of the corresponding AM type whose
+destination address is the local address or the broadcast
+address. Note that since Receive.receive swaps buffers, a program MUST
+NOT instantiate two AMReceivers with the same am_id_t and MUST NOT
+instantiate an AMReceiver and an AMSnoopingReceiver with the same
+am_id_t.</p>
+</div>
+<div class="section">
+<h2><a id="amsnooperc" name="amsnooperc">4.3 AMSnooperC</a></h2>
+<p>AMSnooper has an identical signature to AMReceiver:</p>
+<pre class="literal-block">
+generic configuration AMSnooperC(am_id_t t) {
+  provides{
+    interface Receive;
+    interface Packet;
+    interface AMPacket;
+  }
+}
+</pre>
+<p>AMSnooper.Receive.receive is signalled whenever the packet layer
+receives an active message of the corresponding AM type whose
+destination address is neither to the local address nor the broadcast
+address. Note that since Receive.receive swaps buffers, a program MUST
+NOT instantiate two AMSnoopers with the same am_id_t and MUST NOT
+instantiate an AMSnooper and an AMSnoopingReceiver with the same
+am_id_t.</p>
+</div>
+<div class="section">
+<h2><a id="amsnoopingreceiverc" name="amsnoopingreceiverc">4.4 AMSnoopingReceiverC</a></h2>
+<p>AMSnoopingReceiverC has an identical signature to AMReceiverC:</p>
+<pre class="literal-block">
+generic configuration AMSnoopingReceiverC(am_id_t t) {
+  provides{
+    interface Receive;
+    interface Packet;
+    interface AMPacket;
+  }
+}
+</pre>
+<p>AMSnoopingReceiverC.Receive.receive is signalled whenever the packet
+layer receives an active message of the corresponding AM type,
+regardless of destination address. Note that since Receive.receive
+swaps buffers, a program that instantiates an AMSnoopingReceiverC with
+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>
+<p>AMSenderC has the following signature:</p>
+<pre class="literal-block">
+generic configuration AMSenderC(am_id_t AMId) {
+  provides {
+    interface AMSend;
+    interface Packet;
+    interface AMPacket;
+    interface PacketAcknowledgements as Acks;
+  }
+}
+</pre>
+<p>Because this is a send virtualization, AMSenderC.AMSend.send returns
+EBUSY only if there is a send request outstanding on this particular
+AMSenderC. That is, each AMSenderC has a queue of depth one. The exact
+order in which pending AMSenderC requests are serviced is undefined,
+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 class="section">
+<h2><a id="power-management" name="power-management">4.6 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
+application has to call ActiveMessageC.SplitControl.start().
+The HAL underneath ActiveMessageC  MAY employ power management
+techniques, such as TDMA scheduling or low power listening, when
+&quot;on.&quot;</p>
+</div>
+</div>
+<div class="section">
+<h1><a id="hal-requirements" name="hal-requirements">5. HAL Requirements</a></h1>
+<p>A radio chip <em>X</em> MUST have a packet abstraction with the following
+signature:</p>
+<pre class="literal-block">
+provides interface Init;
+provides interface SplitControl;
+provides interface AMSend[am_id_t type];
+provides interface Receive[am_id_t type];
+provides interface Receive as Snoop[am_id_t type];
+provides interface Packet;
+provides interface AMPacket;
+provides interface PacketAcknowledgments;
+</pre>
+<p>The component SHOULD be named <em>XActiveMessageC</em>, where <em>X</em> is
+the name of the radio chip. The component MAY have additional interfaces.
+These interfaces can either be chip-specific or chip-independent.</p>
+</div>
+<div class="section">
+<h1><a id="message-t" name="message-t">6. message_t</a></h1>
+<p>Active messages are a basic single-hop packet abstraction. Therefore,
+following TEP 111 <a class="footnote-reference" href="#id8" id="id4" name="id4">[3]</a>, all data link and active message headers
+MUST be in the <tt class="docutils literal"><span class="pre">message_header_t</span></tt> structure of message_t. This ensures
+that an active message received from one data link layer (e.g., the radio)
+can be passed to another data link layer (e.g., the UART) without
+shifting the data payload. This means that the <tt class="docutils literal"><span class="pre">message_header_t</span></tt> must
+include all data needed for AM fields, which might introduce headers
+in addition to those of the data link. For example, this is the
+structure of the CC2420 header:</p>
+<pre class="literal-block">
+typedef nx_struct cc2420_header_t {
+  nx_uint8_t length;
+  nx_uint16_t fcf;
+  nx_uint8_t dsn;
+  nx_uint16_t destpan;
+  nx_uint16_t dest;
+  nx_uint16_t src;
+  nx_uint8_t type;
+} cc2420_header_t;
+</pre>
+<p>The first six fields (length through src) are all 802.15.4 headers. The
+type field, however, has been added to the header structure in order
+to support AM dispatch.</p>
+</div>
+<div class="section">
+<h1><a id="implementation" name="implementation">7. Implementation</a></h1>
+<p>The following files in <tt class="docutils literal"><span class="pre">tinyos-2.x/tos/system</span></tt> provide reference
+implementations of the abstractions described in this TEP.</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">AMSenderC.nc</span></tt>, <tt class="docutils literal"><span class="pre">AMReceiverC.nc</span></tt>, <tt class="docutils literal"><span class="pre">AMSnooperC.nc</span></tt>,
+and <tt class="docutils literal"><span class="pre">AMSnoopingReceiverC.nc</span></tt> are implementations of
+virtualized AM services.</li>
+<li><tt class="docutils literal"><span class="pre">AMQueueP</span></tt> provides a send queue of <em>n</em> entries for <em>n</em>
+AMSenderC clients, such that each client has a dedicated entry.</li>
+<li><tt class="docutils literal"><span class="pre">AMQueueImplP</span></tt> is the underlying queue implementation,
+which is reusable for different clients (it is also used
+in the serial stack <a class="footnote-reference" href="#id9" id="id5" name="id5">[4]</a>).</li>
+<li><tt class="docutils literal"><span class="pre">AMQueueEntryP</span></tt> sits on top of <tt class="docutils literal"><span class="pre">AMQueueP</span></tt> and stores
+the parameters to <tt class="docutils literal"><span class="pre">AMSend.send</span></tt> in an outstanding
+packet with the <tt class="docutils literal"><span class="pre">AMPacket</span></tt> interface.</li>
+</ul>
+</blockquote>
+<p>The following files in <tt class="docutils literal"><span class="pre">tinyos-2.x/tos/interfaces</span></tt> contain
+example implementations of packet protocol interfaces:</p>
+<blockquote>
+<ul>
+<li><p class="first"><tt class="docutils literal"><span class="pre">Packet.nc</span></tt> is the basic interface that almost all
+packet protocols provide.</p>
+</li>
+<li><dl class="first docutils">
+<dt><tt class="docutils literal"><span class="pre">Send.nc</span></tt> is the transmission interface for address-free</dt>
+<dd><p class="first last">protocols.</p>
+</dd>
+</dl>
+</li>
+<li><dl class="first docutils">
+<dt><tt class="docutils literal"><span class="pre">AMSend.nc</span></tt> is the transmission interface for AM address</dt>
+<dd><p class="first last">send protocols.</p>
+</dd>
+</dl>
+</li>
+<li><p class="first"><tt class="docutils literal"><span class="pre">AMPacket.nc</span></tt> is the packet interface for AM-specific
+fields.</p>
+</li>
+</ul>
+</blockquote>
+<p>An active messaging implementation for the CC2420 radio chip
+can be found in <tt class="docutils literal"><span class="pre">tos/chips/CC2420/CC2420ActiveMessageC.nc</span></tt>.
+The micaz platform and telos family have an <tt class="docutils literal"><span class="pre">ActiveMessageC.nc</span></tt>
+which exports the interfaces of <tt class="docutils literal"><span class="pre">CC2420ActiveMessageC</span></tt>.</p>
+</div>
+<div class="section">
+<h1><a id="author-s-address" name="author-s-address">8. Author's Address</a></h1>
+<div class="line-block">
+<div class="line">Philip Levis</div>
+<div class="line">358 Gates Hall</div>
+<div class="line">Computer Science Laboratory</div>
+<div class="line">Stanford University</div>
+<div class="line">Stanford, CA 94305</div>
+<div class="line"><br /></div>
+<div class="line">phone - +1 650 725 9046</div>
+</div>
+</div>
+<div class="section">
+<h1><a id="citations" name="citations">9. Citations</a></h1>
+<table class="docutils footnote" frame="void" id="id6" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="id6">[1]</a></td><td>The MintRoute protocol. <tt class="docutils literal"><span class="pre">tinyos-1.x/tos/lib/MintRoute</span></tt>. Also, A. Woo, T. Tong, and D. Culler. &quot;Taming the Underlying Challenges of Reliable Multihop Routing in Sensor Networks.&quot; SenSys 2003.</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id7" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id2" name="id7">[2]</a></td><td>Tiny AGgregation, one protocol of the TinyDB system.  <tt class="docutils literal"><span class="pre">tinyos-1.x/tos/lib/TinyDB</span></tt>. Also, S. Madden and M. Franklin and J. Hellerstein and W. Hong. &quot;TinyDB: An Acquisitional Query Processing System for Sensor Networks.&quot; Transactions on Database Systems (TODS) 2005.</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id8" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id8">[3]</a></td><td><em>(<a class="fn-backref" href="#id3">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> TEP 111: message_t.</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id9" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id5" name="id9">[4]</a></td><td>TEP 113: Serial Communication.</td></tr>
+</tbody>
+</table>
+</div>
+</div>
+</body>
+</html>