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

📄 ctpforwardingenginep.nc

📁 tinyos2.0版本驱动
💻 NC
📖 第 1 页 / 共 3 页
字号:
/* $Id: CtpForwardingEngineP.nc,v 1.13 2008/06/04 04:30:41 regehr 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: 2008/06/04 04:30:41 $ */#include <CtpForwardingEngine.h>#include <CtpDebugMsg.h>   generic module CtpForwardingEngineP() {  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;    interface CtpPacket;    interface CtpCongestion;  }  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 LinkEstimator;    // Counts down from the last time we heard from our parent; used    // to expire local state about parent congestion.    interface Timer<TMilli> as CongestionTimer;    interface Cache<message_t*> as SentCache;    interface CtpInfo;    interface PacketAcknowledgements;    interface Random;    interface RootControl;    interface CollectionId[uint8_t client];    interface AMPacket;    interface CollectionDebug;    interface Leds;  }}implementation {  /* Helper functions to start the given 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);  static void startCongestionTimer(uint16_t mask, uint16_t offset);  /* Indicates whether our client is congested */  bool clientCongested = FALSE;  /* Tracks our parent's congestion state. */  bool parentCongested = FALSE;  /* Threshold for congestion */  uint8_t congestionThreshold;  /* 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_CTP_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* ONE_NOK 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* ONE_NOK 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]);    }    congestionThreshold = (call SendQueue.maxSize()) >> 1;    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;    }  }  ctp_data_header_t* getHeader(message_t* m) {    return (ctp_data_header_t*)call SubPacket.getPayload(m, sizeof(ctp_data_header_t));  }   /*   * 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) {    ctp_data_header_t* hdr;    fe_queue_entry_t *qe;    dbg("Forwarder", "%s: sending packet from client %hhu: %x, len %hhu\n", __FUNCTION__, client, msg, len);    if (!running) {return EOFF;}    if (len > call Send.maxPayloadLength[client]()) {return ESIZE;}        call Packet.setPayloadLength(msg, len);    hdr = getHeader(msg);    hdr->origin = TOS_NODE_ID;    hdr->originSeqNo  = seqno++;    hdr->type = call CollectionId.fetch[client]();    hdr->thl = 0;    if (clientPtrs[client] == NULL) {      dbg("Forwarder", "%s: send failed as client is busy.\n", __FUNCTION__);      return EBUSY;    }    qe = clientPtrs[client];    qe->msg = msg;    qe->client = client;    qe->retries = MAX_RETRIES;    dbg("Forwarder", "%s: queue entry for %hhu is %hhu deep\n", __FUNCTION__, client, call SendQueue.size());    if (call SendQueue.enqueue(qe) == SUCCESS) {      if (radioOn && !call RetxmitTimer.isRunning()) {        post sendTask();      }      clientPtrs[client] = NULL;

⌨️ 快捷键说明

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