⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tep111.txt

📁 tinyos-2.x.rar
💻 TXT
📖 第 1 页 / 共 2 页
字号:
============================
message_t
============================

:TEP: 111
:Group: Core Working Group 
:Type: Documentary
:Status: Final
:TinyOS-Version: 2.x
:Author: Philip Levis

.. Note::

   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.

Abstract
====================================================================

This memo covers the TinyOS 2.x message buffer abstraction, ``message_t``.
It describes the message buffer design considerations, how and where 
``message_t`` is specified, and how data link layers should access it.
The major goal of ``message_t`` is to allow datagrams to be passed between
different link layers as a contiguous region of memory with zero copies.

1. Introduction
====================================================================

In TinyOS 1.x, a message buffer is a ``TOS_Msg``. A buffer contains an
active message (AM) packet as well as packet metadata, such as timestamps,
acknowledgement bits, and signal strength if the packet was received.
``TOS_Msg`` is a fixed size structure whose size is defined by the maximum
AM payload length (the default is 29 bytes). Fixed sized buffers allows
TinyOS 1.x to have zero-copy semantics: when a component receives a
buffer, rather than copy out the contents it can return a pointer
to a new buffer for the underlying layer to use for the next received 
packet.

One issue that arises is what defines the ``TOS_Msg`` structure, as different
link layers may require different layouts. For example, 802.15.4 radio 
hardware (such as the CC2420, used in the Telos and micaZ platforms) 
may require 802.15.4 headers, while a software stack built on top of
byte radios (such as the CC1000, used in the mica2 platform) can specify 
its own packet format. This means that ``TOS_Msg`` may be different on
different platforms.

The solution to this problem in TinyOS 1.x is for there to be a standard
definition of ``TOS_Msg``, which a platform (e.g., the micaZ) can
redefine to match its radio. For example, a mica2 mote uses the standard 
definition, which is::

  typedef struct TOS_Msg {
    // The following fields are transmitted/received on the radio.
    uint16_t addr;
    uint8_t type;
    uint8_t group;
    uint8_t length;
    int8_t data[TOSH_DATA_LENGTH];
    uint16_t crc;

    // The following fields are not actually transmitted or received
    // on the radio! They are used for internal accounting only.
    // The reason they are in this structure is that the AM interface
    // requires them to be part of the TOS_Msg that is passed to
    // send/receive operations.
    uint16_t strength;
    uint8_t ack;
    uint16_t time;
    uint8_t sendSecurityMode;
    uint8_t receiveSecurityMode;
  } TOS_Msg;

while on a mote with a CC2420 radio (e.g., micaZ), ``TOS_Msg`` is defined as::

  typedef struct TOS_Msg {
    // The following fields are transmitted/received on the radio.
    uint8_t length;
    uint8_t fcfhi;
    uint8_t fcflo;
    uint8_t dsn;
    uint16_t destpan;
    uint16_t addr;
    uint8_t type;
    uint8_t group;
    int8_t data[TOSH_DATA_LENGTH];
    
    // The following fields are not actually transmitted or received
    // on the radio! They are used for internal accounting only.
    // The reason they are in this structure is that the AM interface
    // requires them to be part of the TOS_Msg that is passed to
    // send/receive operations.
    
    uint8_t strength;
    uint8_t lqi;
    bool crc;
    uint8_t ack;
    uint16_t time;
   } TOS_Msg;

There are two basic problems with this approach. First, exposing all of
the link layer fields leads components to directly access the packet
structure. This introduces dependencies between higher level components
and the structure layout. For example, many network services built on
top of data link layers care whether sent packets are acknowledged. They
therefore check the ``ack`` field of ``TOS_Msg``. If a link layer does not 
provide acknowledgements, it must still include the ``ack`` field
and always set it to 0, wasting a byte of RAM per buffer.

Second, this model does not easily support multiple data link layers.
Radio chip implementations assume that the fields they require are 
defined in the structure and directly access them. If a platform
has two different link layers (e.g., a CC1000 *and* a CC2420 radio),
then a ``TOS_Msg`` needs to allocate the right amount of space for both
of their headers while allowing implementations to directly access
header fields. This is very difficult to do in C.

The ``data`` payload is especially problematic. Many
components refer to this field, so it must be at a fixed offset
from the beginning of the structure.
Depending on the underlying link layer, the header fields 
preceding it might have different lengths, and packet-level radios
often require packets to be contiguous memory regions. Overall, these 
complexities make specifying the format of ``TOS_Msg`` very difficult.

TinyOS has traditionally used statically sized packet buffers,
rather than more dynamic approaches, such as scatter-gather I/O
in UNIX sockets (see the man page for ``recv(2)`` for details). 
TinyOS 2.x continues this approach.

2. message_t
====================================================================

In TinyOS 2.x, the standard message buffer is ``message_t``. The
message_t structure is defined in ``tos/types/message.h``::

  typedef nx_struct message_t {
    nx_uint8_t header[sizeof(message_header_t)];
    nx_uint8_t data[TOSH_DATA_LENGTH];
    nx_uint8_t footer[sizeof(message_footer_t)];
    nx_uint8_t metadata[sizeof(message_metadata_t)];
  } message_t;

This format keeps data at a fixed offset on a platform, which 
is important when
passing a message buffer between two different link layers. If the
data payload were at different offsets for different link layers, then
passing a packet between two link layers would require a ``memmove(3)``
operation (essentially, a copy). Unlike in TinyOS 1.x, where TOS_Msg
as explicitly an active messaging packet, message_t is a more general
data-link buffer. In practice, most data-link layers in TinyOS 2.x 
provide active messaging, but it is possible for a non-AM stack to 
share message_t with AM stacks.

The header, footer, and metadata formats are all opaque. Source code
cannot access fields directly. Instead, data-link layers provide access
to fields through nesC interfaces.  Section 3 discusses this in 
greater depth.

Every link layer defines its header, footer, and metadata
structures. These structures MUST be external structs (``nx_struct``), 
and all of their fields MUST be external types (``nx_*``), for two 
reasons. First, external types ensure cross-platform compatibility [1]_.
Second, it forces structures to be aligned on byte boundaries, 
circumventing issues with the 
alignment of packet buffers and field offsets within them. Metadata fields
must be nx_structs for when complete packets are forwarded to the serial
port in order to log traffic.
For example, the CC1000 radio implementation defines
its structures in ``CC1000Msg.h``::

  typedef nx_struct cc1000_header {
    nx_am_addr_t addr;
    nx_uint8_t length;
    nx_am_group_t group;
    nx_am_id_t type;
  } cc1000_header_t;

  typedef nx_struct cc1000_footer {
    nxle_uint16_t crc;
  } cc1000_footer_t;

  typedef nx_struct cc1000_metadata {
    nx_uint16_t strength;
    nx_uint8_t ack;
    nx_uint16_t time;
    nx_uint8_t sendSecurityMode;
    nx_uint8_t receiveSecurityMode;
  } cc1000_metadata_t;

Each link layer defines its structures, but a **platform** is
responsible for defining ``message_header_t``, ``message_footer_t``,
and ``message_metadata_t``. This is because a platform may have
multiple link layers, and so only it can resolve which structures are
needed. These definitions MUST be in a file in a platform directory
named ``platform_message.h``. The mica2 platform, for example, has
two data link layers: the CC1000 radio and the TinyOS serial
stack [2]_. The serial packet format does not have a footer
or metadata section. The ``platform_message.h`` of the mica2
looks like this::

  typedef union message_header {
    cc1000_header_t cc1k; 
    serial_header_t serial;
  } message_header_t;

  typedef union message_footer {
    cc1000_footer_t cc1k;
  } message_footer_t;
  
  typedef union message_metadata {
    cc1000_metadata cc1k;
  } message_metadata_t;

For a more complex example, consider a fictional platform named
'megamica' that has both a CC1000 and a CC2420 radio. Its
``platform_message.h`` would look like this::

  typedef union mega_mica_header {
    cc1000_header_t cc1k;
    cc2420_header_t cc2420;
    serial_header_t serial;
  } message_header_t;

  typedef union mega_mica_footer {
    cc1000_footer_t cc1k;
    cc2420_footer_t cc2420;
  } message_footer_t;

  typedef union mega_mica_metadata {
    cc1000_metadata_t cc1k;
    cc2420_metadata_t cc2420;
  } message__metadata_t;
 
If a platform has more than one link layer, it SHOULD define each of the
message_t fields to be a union of the underlying link layer structures.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -