forwardingenginep.nc

来自「tinyos-2.0源代码!转载而已!要的尽管拿!」· NC 代码 · 共 861 行 · 第 1/3 页

NC
861
字号
/* $Id: ForwardingEngineP.nc,v 1.1.2.45 2006/06/26 22:55:33 scipio Exp $ *//* * Copyright (c) 2006 Stanford University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * - Redistributions of source code must retain the above copyright *   notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright *   notice, this list of conditions and the following disclaimer in the *   documentation and/or other materials provided with the *   distribution. * - Neither the name of the Stanford University nor the names of *   its contributors may be used to endorse or promote products derived *   from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL STANFORD * UNIVERSITY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. *//** *  The ForwardingEngine is responsible for queueing and scheduling outgoing *  packets in a collection protocol. It maintains a pool of forwarding messages  *  and a packet send  *  queue. A ForwardingEngine with a forwarding message pool of size <i>F</i>  *  and <i>C</i> CollectionSenderC clients has a send queue of size *  <i>F + C</i>. This implementation has a large number of configuration *  constants, which can be found in <code>ForwardingEngine.h</code>. * *  <p>Packets in the send queue are sent in FIFO order, with head-of-line *  blocking. Because this is a tree collection protocol, all packets are going *  to the same destination, and so the ForwardingEngine does not distinguish *  packets from one another: packets from CollectionSenderC clients are *  treated identically to forwarded packets.</p> * *  <p>If ForwardingEngine is on top of a link layer that supports *  synchronous acknowledgments, it enables them and retransmits packets *  when they are not acked. It transmits a packet up to MAX_RETRIES times *  before giving up and dropping the packet.</p>  * *  <p>The ForwardingEngine detects routing loops and tries to correct *  them. It assumes that the collection tree is based on a gradient, *  such as hop count or estimated transmissions. When the ForwardingEngine *  sends a packet to the next hop, it puts the local gradient value in *  the packet header. If a node receives a packet to forward whose *  gradient value is less than its own, then the gradient is not monotonically *  decreasing and there may be a routing loop. When the ForwardingEngine *  receives such a packet, it tells the RoutingEngine to advertise its *  gradient value soon, with the hope that the advertisement will update *  the node who just sent a packet and break the loop. *   *  <p>ForwardingEngine times its packet transmissions. It differentiates *  between four transmission cases: forwarding, success, ack failure,  *  and loop detection. In each case, the *  ForwardingEngine waits a randomized period of time before sending the next *  packet. This approach assumes that the network is operating at low *  utilization; its goal is to prevent correlated traffic -- such as  *  nodes along a route forwarding packets -- from interfering with itself. * *  <table> *    <tr> *      <td><b>Case</b></td> *      <td><b>CC2420 Wait (ms)</b></td> *      <td><b>Other Wait (ms)</b></td> *      <td><b>Description</b></td> *    </tr> *    <tr> *      <td>Forwarding</td> *      <td>Immediate</td> *      <td>Immediate</td> *      <td>When the ForwardingEngine receives a packet to forward and it is not *          already sending a packet (queue is empty). In this case, it immediately *          forwards the packet.</td> *    </tr> *    <tr> *      <td>Success</td> *      <td>16-31</td> *      <td>128-255</td> *      <td>When the ForwardingEngine successfully sends a packet to the next *          hop, it waits this long before sending the next packet in the queue. *          </td> *    </tr> *    <tr> *      <td>Ack Failure</td> *      <td>8-15</td> *      <td>128-255</td> *      <td>If the link layer supports acks and the ForwardingEngine did not *          receive an acknowledgment from the next hop, it waits this long before *          trying a retransmission. If the packet has exceeded the retransmission *          count, ForwardingEngine drops the packet and uses the Success timer instead. </td> *    </tr> *    <tr> *      <td>Loop Detection</td> *      <td>32-63</td> *      <td>512-1023</td> *      <td>If the ForwardingEngine is asked to forward a packet from a node that *          believes it is closer to the root, the ForwardingEngine pauses its *          transmissions for this interval and triggers the RoutingEngine to  *          send an update. The goal is to let the gradient become consistent before *          sending packets, in order to prevent routing loops from consuming *          bandwidth and energy.</td> *    </tr> *  </table>   * *  <p>The times above are all for CC2420-based platforms. The timings for *  other platforms depend on their bit rates, as they are based on packet *  transmission times.</p> *  @author Philip Levis *  @author Kyle Jamieson *  @date   $Date: 2006/06/26 22:55:33 $ */#include <ForwardingEngine.h>#include "CollectionDebugMsg.h"   generic module ForwardingEngineP() {  provides {    interface Init;    interface StdControl;    interface Send[uint8_t client];    interface Receive[collection_id_t id];    interface Receive as Snoop[collection_id_t id];    interface Intercept[collection_id_t id];    interface Packet;    interface CollectionPacket;  }  uses {    interface AMSend as SubSend;    interface Receive as SubReceive;    interface Receive as SubSnoop;    interface Packet as SubPacket;    interface UnicastNameFreeRouting;    interface SplitControl as RadioControl;    interface Queue<fe_queue_entry_t*> as SendQueue;    interface Pool<fe_queue_entry_t> as QEntryPool;    interface Pool<message_t> as MessagePool;    interface Timer<TMilli> as RetxmitTimer;    interface Cache<uint32_t> as SentCache;    interface TreeRoutingInspect;    interface PacketAcknowledgements;    interface Random;    interface RootControl;    interface CollectionId[uint8_t client];    interface AMPacket;    interface CollectionDebug;  }}implementation {  /* Starts the retxmit timer with a random number masked by the given   * mask and added to the given offset.   */  static void startRetxmitTimer(uint16_t mask, uint16_t offset);  /* Keeps track of whether the routing layer is running; if not,   * it will not send packets. */  bool running = FALSE;  /* Keeps track of whether the radio is on; no sense sending packets   * if the radio is off. */  bool radioOn = FALSE;  /* Keeps track of whether an ack is pending on an outgoing packet,   * so that the engine can work unreliably when the data-link layer   * does not support acks. */  bool ackPending = FALSE;  /* Keeps track of whether the packet on the head of the queue   * is being used, and control access to the data-link layer.*/  bool sending = FALSE;  /* Keep track of the last parent address we sent to, so that     unacked packets to an old parent are not incorrectly attributed     to a new parent. */  am_addr_t lastParent;    /* Network-level sequence number, so that receivers   * can distinguish retransmissions from different packets. */  uint8_t seqno;  enum {    CLIENT_COUNT = uniqueCount(UQ_COLLECTION_CLIENT)  };  /* Each sending client has its own reserved queue entry.     If the client has a packet pending, its queue entry is in the      queue, and its clientPtr is NULL. If the client is idle,     its queue entry is pointed to by clientPtrs. */  fe_queue_entry_t clientEntries[CLIENT_COUNT];  fe_queue_entry_t* clientPtrs[CLIENT_COUNT];  /* The loopback message is for when a collection roots calls     Send.send. Since Send passes a pointer but Receive allows     buffer swaps, the forwarder copies the sent packet into      the loopbackMsgPtr and performs a buffer swap with it.     See sendTask(). */       message_t loopbackMsg;  message_t* loopbackMsgPtr;  command error_t Init.init() {    int i;    for (i = 0; i < CLIENT_COUNT; i++) {      clientPtrs[i] = clientEntries + i;      dbg("Forwarder", "clientPtrs[%hhu] = %p\n", i, clientPtrs[i]);    }    loopbackMsgPtr = &loopbackMsg;    lastParent = call AMPacket.address();    seqno = 0;    return SUCCESS;  }  command error_t StdControl.start() {    running = TRUE;    return SUCCESS;  }  command error_t StdControl.stop() {    running = FALSE;    return SUCCESS;  }  /* sendTask is where the first phase of all send logic   * exists (the second phase is in SubSend.sendDone()). */  task void sendTask();    /* ForwardingEngine keeps track of whether the underlying     radio is powered on. If not, it enqueues packets;     when it turns on, it then starts sending packets. */   event void RadioControl.startDone(error_t err) {    if (err == SUCCESS) {      radioOn = TRUE;      if (!call SendQueue.empty()) {        post sendTask();      }    }  }   /*    * If the ForwardingEngine has stopped sending packets because   * these has been no route, then as soon as one is found, start   * sending packets.   */   event void UnicastNameFreeRouting.routeFound() {    post sendTask();  }  event void UnicastNameFreeRouting.noRoute() {    // Depend on the sendTask to take care of this case;    // if there is no route the component will just resume    // operation on the routeFound event  }    event void RadioControl.stopDone(error_t err) {    if (err == SUCCESS) {      radioOn = FALSE;    }  }  network_header_t* getHeader(message_t* m) {    return (network_header_t*)call SubPacket.getPayload(m, NULL);  }   /*   * The send call from a client. Return EBUSY if the client is busy   * (clientPtrs is NULL), otherwise configure its queue entry   * and put it in the send queue. If the ForwardingEngine is not   * already sending packets (the RetxmitTimer isn't running), post   * sendTask. It could be that the engine is running and sendTask   * has already been posted, but the post-once semantics make this   * not matter.   */   command error_t Send.send[uint8_t client](message_t* msg, uint8_t len) {    network_header_t* hdr;

⌨️ 快捷键说明

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