📄 ctproutingenginep.nc
字号:
#include <Timer.h>
#include <TreeRouting.h>
#include <CollectionDebugMsg.h>
/* $Id: CtpRoutingEngineP.nc,v 1.21 2009/09/21 02:19:42 gnawali 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: 2009/09/21 02:19:42 $
* @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 */
// 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;
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 (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;
/* Metric through current parent, initially infinity */
currentEtx = MAX_METRIC;
dbg("TreeRouting","%s\n",__FUNCTION__);
/* Find best path in table, other than our current */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -