]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - doc/txt/tep116.txt
Add SharedSplitControlC, for N clients needing shared access to something.
[tinyos-2.x.git] / doc / txt / tep116.txt
index 19a4acd2a6be06a059e251e827cb567dece8975e..50cfdcbd02c542d7d5a55ab79c66529774811073 100644 (file)
@@ -5,15 +5,10 @@ Packet Protocols
 :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
@@ -94,7 +89,10 @@ Packet-level communication has three basic classes of interfaces.
 *Packet* interfaces are for accessing message fields and payloads. 
 *Send* interfaces are for transmitting packets, and are
 distinguished by their addressing scheme. 
-Finally, the *Receive* interface is for handling packet reception events.
+The *Receive* 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.
 
 2.1 Packet interfaces
 --------------------------------------------------------------------
@@ -119,39 +117,56 @@ The Packet interface defines this mechanism::
     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;
@@ -167,9 +182,11 @@ layer. For example, if there is a network that introduces
     };
  
     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) {
@@ -184,12 +201,12 @@ layer. For example, if there is a network that introduces
       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;
     } 
   }
 
@@ -218,17 +235,32 @@ has this signature::
   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.
+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
 --------------------------------------------------------------------
@@ -246,7 +278,7 @@ basic, address-free Send 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);
   }
 
 while this is the AMSend interface::
@@ -257,18 +289,42 @@ 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
+maximum transfer unit (MTU), the send command MUST return ESIZE.
+
+The ``Send`` and ``AMSend`` interfaces have an explicit queue of
+depth one. A call to ``send`` on either of these interfaces MUST 
+return EBUSY if a prior call to ``send`` returned SUCCESS but no
+``sendDone`` event has been signaled yet. More explicitly::
+
+  if (call Send.send(...) == SUCCESS &&
+      call Send.send(...) == SUCCESS) {
+     // This block is unreachable.
+  }
+
+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.
+
+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.
+
 2.3 Receive interface
 --------------------------------------------------------------------
 
@@ -276,32 +332,29 @@ Receive is the interface for receiving packets. It has this signature::
 
   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.
@@ -309,9 +362,9 @@ packet reception.
 A *user* of the Receive interface has three basic options when it
 handles a receive event:
 
-1) Return ``msg`` without touching it.
-2) Copy some data out of ``payload`` and return ``msg``.
-3) Store ``msg`` in its local frame and return a different ``message_t*`` for the lower layer to use.
+  1) Return ``msg`` without touching it.
+  2) Copy some data out of ``payload`` and return ``msg``.
+  3) Store ``msg`` in its local frame and return a different ``message_t*`` for the lower layer to use.
 
 These are simple code examples of the three cases::
 
@@ -350,8 +403,8 @@ the signaling of ``receive.``
 --------------------------------------------------------------------
 
 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
@@ -487,7 +540,7 @@ 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.
 
-4.5 AMSender 
+4.5 AMSenderC 
 --------------------------------------------------------------------
 
 AMSenderC has the following signature::
@@ -509,7 +562,14 @@ 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.
 
-4.6 Power Management
+5. Power Management and Local Address
+============================================================================
+
+In addition to standard datapath interfaces for sending and
+receiving packets, an active message layer also has control interfaces.
+
+
+5.1 Power Management
 --------------------------------------------------------------------
 
 The communication virtualizations do not support power management.
@@ -520,6 +580,18 @@ The HAL underneath ActiveMessageC  MAY employ power management
 techniques, such as TDMA scheduling or low power listening, when
 "on."
 
+5.2 Local Active Message Address
+--------------------------------------------------------------------
+
+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
+``ActiveMessageAddressC``. 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.
+
 5. HAL Requirements
 ============================================================================
 
@@ -625,6 +697,3 @@ which exports the interfaces of ``CC2420ActiveMessageC``.
 
 .. [4] TEP 113: Serial Communication.
 
-
-