📄 ctproutingenginep.nc
字号:
#include <Timer.h>#include <TreeRouting.h>#include <CollectionDebugMsg.h>/* $Id: CtpRoutingEngineP.nc,v 1.15 2008/06/04 04:30:41 regehr Exp $ *//* * "Copyright (c) 2005 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * *//** * The TreeRoutingEngine is responsible for computing the routes for * collection. It builds a set of trees rooted at specific nodes (roots) and * maintains these trees using information provided by the link estimator on * the quality of one hop links. * * <p>Each node is part of only one tree at any given time, but there is no * difference from the node's point of view of which tree it is part. In other * words, a message is sent towards <i>a</i> root, but which one is not * specified. It is assumed that the roots will work together to have all data * aggregated later if need be. The tree routing engine's responsibility is * for each node to find the path with the least number of transmissions to * any one root. * * <p>The tree is proactively maintained by periodic beacons sent by each * node. These beacons are jittered in time to prevent synchronizations in the * network. All nodes maintain the same <i>average</i> beacon sending rate * (defined by BEACON_INTERVAL +- 50%). The beacon contains the node's parent, * the current hopcount, and the cumulative path quality metric. The metric is * defined as the parent's metric plus the bidirectional quality of the link * between the current node and its parent. The metric represents the * expected number of transmissions along the path to the root, and is 0 by * definition at the root. * * <p>Every time a node receives an update from a neighbor it records the * information if the node is part of the neighbor table. The neighbor table * keeps the best candidates for being parents i.e., the nodes with the best * path metric. The neighbor table does not store the full path metric, * though. It stores the parent's path metric, and the link quality to the * parent is only added when the information is needed: (i) when choosing a * parent and (ii) when choosing a route. The nodes in the neighbor table are * a subset of the nodes in the link estimator table, as a node is not * admitted in the neighbor table with an estimate of infinity. * * <p>There are two uses for the neighbor table, as mentioned above. The first * one is to select a parent. The parent is just the neighbor with the best * path metric. It serves to define the node's own path metric and hopcount, * and the set of child-parent links is what defines the tree. In a sense the * tree is defined to form a coherent propagation substrate for the path * metrics. The parent is (re)-selected periodically, immediately before a * node sends its own beacon, in the updateRouteTask. * * <p>The second use is to actually choose a next hop towards any root at * message forwarding time. This need not be the current parent, even though * it is currently implemented as such. * * <p>The operation of the routing engine has two main tasks and one main * event: updateRouteTask is called periodically and chooses a new parent; * sendBeaconTask broadcasts the current route information to the neighbors. * The main event is the receiving of a neighbor's beacon, which updates the * neighbor table. * * <p> The interface with the ForwardingEngine occurs through the nextHop() * call. * * <p> Any node can become a root, and routed messages from a subset of the * network will be routed towards it. The RootControl interface allows * setting, unsetting, and querying the root state of a node. By convention, * when a node is root its hopcount and metric are 0, and the parent is * itself. A root always has a valid route, to itself. * * @author Rodrigo Fonseca * @author Philip Levis (added trickle-like updates) * Acknowledgment: based on MintRoute, MultiHopLQI, BVR tree construction, Berkeley's MTree * * @date $Date: 2008/06/04 04:30:41 $ * @see Net2-WG */generic module CtpRoutingEngineP(uint8_t routingTableSize, uint32_t minInterval, uint32_t maxInterval) { provides { interface UnicastNameFreeRouting as Routing; interface RootControl; interface CtpInfo; interface StdControl; interface CtpRoutingPacket; interface Init; } uses { interface AMSend as BeaconSend; interface Receive as BeaconReceive; interface LinkEstimator; interface AMPacket; interface SplitControl as RadioControl; interface Timer<TMilli> as BeaconTimer; interface Timer<TMilli> as RouteTimer; interface Random; interface CollectionDebug; interface CtpCongestion; interface CompareBit; }}implementation { bool ECNOff = TRUE; /* Keeps track of whether the radio is on. No sense updating or sending * beacons if radio is off */ bool radioOn = FALSE; /* Controls whether the node's periodic timer will fire. The node will not * send any beacon, and will not update the route. Start and stop control this. */ bool running = FALSE; /* Guards the beacon buffer: only one beacon being sent at a time */ bool sending = FALSE; /* Tells updateNeighbor that the parent was just evicted.*/ bool justEvicted = FALSE; route_info_t routeInfo; bool state_is_root; am_addr_t my_ll_addr; message_t beaconMsgBuffer; ctp_routing_header_t* beaconMsg; /* routing table -- routing info about neighbors */ routing_table_entry routingTable[routingTableSize]; uint8_t routingTableActive; /* statistics */ uint32_t parentChanges; /* end statistics */ uint32_t routeUpdateTimerCount; // Maximimum it takes to hear four beacons enum { DEATH_TEST_INTERVAL = (maxInterval * 4) / (BEACON_INTERVAL / 1024), }; // forward declarations void routingTableInit(); uint8_t routingTableFind(am_addr_t); error_t routingTableUpdateEntry(am_addr_t, am_addr_t , uint16_t); error_t routingTableEvict(am_addr_t neighbor); uint32_t currentInterval = minInterval; uint32_t t; bool tHasPassed; void chooseAdvertiseTime() { t = currentInterval; t /= 2; t += call Random.rand32() % t; tHasPassed = FALSE; call BeaconTimer.stop(); call BeaconTimer.startOneShot(t); } void resetInterval() { currentInterval = minInterval; chooseAdvertiseTime(); } void decayInterval() { currentInterval *= 2; if (currentInterval > maxInterval) { currentInterval = maxInterval; } chooseAdvertiseTime(); } void remainingInterval() { uint32_t remaining = currentInterval; remaining -= t; tHasPassed = TRUE; call BeaconTimer.startOneShot(remaining); } command error_t Init.init() { uint8_t maxLength; routeUpdateTimerCount = 0; radioOn = FALSE; running = FALSE; parentChanges = 0; state_is_root = 0; routeInfoInit(&routeInfo); routingTableInit(); my_ll_addr = call AMPacket.address(); beaconMsg = call BeaconSend.getPayload(&beaconMsgBuffer, call BeaconSend.maxPayloadLength()); maxLength = call BeaconSend.maxPayloadLength(); dbg("TreeRoutingCtl","TreeRouting initialized. (used payload:%d max payload:%d!\n", sizeof(beaconMsg), maxLength); return SUCCESS; } command error_t StdControl.start() { //start will (re)start the sending of messages if (!running) { running = TRUE; resetInterval(); call RouteTimer.startPeriodic(BEACON_INTERVAL); dbg("TreeRoutingCtl","%s running: %d radioOn: %d\n", __FUNCTION__, running, radioOn); } return SUCCESS; } command error_t StdControl.stop() { running = FALSE; dbg("TreeRoutingCtl","%s running: %d radioOn: %d\n", __FUNCTION__, running, radioOn); return SUCCESS; } event void RadioControl.startDone(error_t error) { radioOn = TRUE; dbg("TreeRoutingCtl","%s running: %d radioOn: %d\n", __FUNCTION__, running, radioOn); if (running) { uint16_t nextInt; nextInt = call Random.rand16() % BEACON_INTERVAL; nextInt += BEACON_INTERVAL >> 1; call BeaconTimer.startOneShot(nextInt); } } event void RadioControl.stopDone(error_t error) { radioOn = FALSE; dbg("TreeRoutingCtl","%s running: %d radioOn: %d\n", __FUNCTION__, running, radioOn); } /* Is this quality measure better than the minimum threshold? */ // Implemented assuming quality is EETX bool passLinkEtxThreshold(uint16_t etx) { return TRUE; return (etx < ETX_THRESHOLD); } /* Converts the output of the link estimator to path metric * units, that can be *added* to form path metric measures */ uint16_t evaluateEtx(uint16_t quality) { //dbg("TreeRouting","%s %d -> %d\n",__FUNCTION__,quality, quality+10); return (quality + 10); } /* updates the routing information, using the info that has been received * from neighbor beacons. Two things can cause this info to change: * neighbor beacons, changes in link estimates, including neighbor eviction */ task void updateRouteTask() { uint8_t i; routing_table_entry* entry; routing_table_entry* best; uint16_t minEtx; uint16_t currentEtx; uint16_t linkEtx, pathEtx; if (state_is_root) return; best = NULL; /* Minimum etx found among neighbors, initially infinity */ minEtx = MAX_METRIC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -