[Tinyos-contrib-commits]
CVS: tinyos-1.x/contrib/GGB/tos/lib/MintRoute
FixRoute.nc, NONE, 1.1 MultiHop.h, NONE,
1.1 MultiHopEngineM.nc, NONE, 1.1 MultiHopWMEWMA.nc, NONE,
1.1 README, NONE, 1.1 WMEWMAMultiHopRouter.nc, NONE, 1.1
Sukun Kim
binetude at users.sourceforge.net
Tue Jun 20 15:05:58 PDT 2006
Update of /cvsroot/tinyos/tinyos-1.x/contrib/GGB/tos/lib/MintRoute
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv15568/MintRoute
Added Files:
FixRoute.nc MultiHop.h MultiHopEngineM.nc MultiHopWMEWMA.nc
README WMEWMAMultiHopRouter.nc
Log Message:
--- NEW FILE: FixRoute.nc ---
interface FixRoute {
command result_t fix();
command result_t release();
command uint8_t getFixedRoute();
command uint16_t getParent();
command uint8_t getDepth();
}
--- NEW FILE: MultiHop.h ---
// $Id: MultiHop.h,v 1.1 2006/06/20 22:05:56 binetude Exp $
/* tab:4
* "Copyright (c) 2000-2003 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."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/*
*
* Authors: Philip Buonadonna, Alec Woo, Terence Tong, Crossbow
* Date last modified: 2/20/03
*
*/
#ifndef _TOS_MULTIHOP_H
#define _TOS_MULTIHOP_H
#include "AM.h"
enum {
AM_MULTIHOPMSG = 250,
AM_DEBUGPACKET = 3
};
/* Fields of neighbor table */
typedef struct TOS_MHopNeighbor {
uint16_t addr; // state provided by nbr
uint16_t recv_count; // since last goodness update
uint16_t fail_count; // since last goodness, adjusted by TOs
int16_t last_seqno;
uint8_t goodness;
uint8_t hopcount;
uint8_t timeouts; // since last recv
} TOS_MHopNeighbor;
typedef struct MultihopMsg {
uint16_t sourceaddr;
uint16_t originaddr;
int16_t seqno;
uint8_t hopcount;
uint8_t data[(TOSH_DATA_LENGTH - 7)];
} __attribute__ ((packed)) TOS_MHopMsg;
typedef struct DBGEstEntry {
uint16_t id;
uint8_t hopcount;
uint8_t sendEst;
} __attribute__ ((packed)) DBGEstEntry;
typedef struct DebugPacket {
uint8_t estEntries;
DBGEstEntry estList[5];
} __attribute__ ((packed)) DebugPacket;
#endif /* _TOS_MULTIHOP_H */
--- NEW FILE: MultiHopEngineM.nc ---
// $Id: MultiHopEngineM.nc,v 1.1 2006/06/20 22:05:56 binetude Exp $
/* tab:4
* "Copyright (c) 2000-2003 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."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/*
* A simple module that handles multihop packet movement. It accepts
* messages from both applications and the network and does the necessary
* interception and forwarding.
* It interfaces to an algorithmic componenet via RouteSelect. It also acts
* as a front end for RouteControl
*/
includes AM;
includes MultiHop;
#ifndef MHOP_QUEUE_SIZE
#define MHOP_QUEUE_SIZE 16
#endif
module MultiHopEngineM {
provides {
interface StdControl;
interface Receive[uint8_t id];
interface Send[uint8_t id];
interface Intercept[uint8_t id];
interface Intercept as Snoop[uint8_t id];
interface RouteControl;
}
uses {
interface ReceiveMsg[uint8_t id];
interface SendMsg[uint8_t id];
interface RouteControl as RouteSelectCntl;
interface RouteSelect;
interface StdControl as SubControl;
interface CommControl;
interface StdControl as CommStdControl;
}
}
implementation {
enum {
FWD_QUEUE_SIZE = MHOP_QUEUE_SIZE, // Forwarding Queue
EMPTY = 0xff
};
/* Routing status of local node */
/* Internal storage and scheduling state */
TOS_Msg FwdBuffers[FWD_QUEUE_SIZE];
TOS_Msg *FwdBufList[FWD_QUEUE_SIZE];
uint8_t iFwdBufHead, iFwdBufTail;
int timer_rate,timer_ticks;
/***********************************************************************
* Initialization
***********************************************************************/
static void initialize() {
int n;
for (n=0; n < FWD_QUEUE_SIZE; n++) {
FwdBufList[n] = &FwdBuffers[n];
}
iFwdBufHead = iFwdBufTail = 0;
}
command result_t StdControl.init() {
initialize();
call CommStdControl.init();
return call SubControl.init();
}
command result_t StdControl.start() {
call CommStdControl.start();
call SubControl.start();
return call CommControl.setPromiscuous(TRUE);
}
command result_t StdControl.stop() {
call SubControl.stop();
// XXX message doesn't get received if we stop then start radio
return call CommStdControl.stop();
}
/***********************************************************************
* Commands and events
***********************************************************************/
command result_t Send.send[uint8_t id](TOS_MsgPtr pMsg, uint16_t PayloadLen) {
uint16_t usMHLength = offsetof(TOS_MHopMsg,data) + PayloadLen;
if (usMHLength > TOSH_DATA_LENGTH) {
return FAIL;
}
//dbg(DBG_ROUTE,"MHop: send\n");
call RouteSelect.initializeFields(pMsg,id);
if (call RouteSelect.selectRoute(pMsg,id) != SUCCESS) {
return FAIL;
}
//dbg(DBG_ROUTE,"MHop: out pkt 0x%x\n",((TOS_MHopMsg *)pMsg->data)->seqno);
if (call SendMsg.send[id](pMsg->addr, usMHLength, pMsg) != SUCCESS) {
return FAIL;
}
return SUCCESS;
}
command void *Send.getBuffer[uint8_t id](TOS_MsgPtr pMsg, uint16_t* length) {
TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)pMsg->data;
*length = TOSH_DATA_LENGTH - offsetof(TOS_MHopMsg,data);
return (&pMHMsg->data[0]);
}
static TOS_MsgPtr mForward(TOS_MsgPtr pMsg, uint8_t id) {
TOS_MsgPtr pNewBuf = pMsg;
if (((iFwdBufHead + 1) % FWD_QUEUE_SIZE) == iFwdBufTail)
return pNewBuf;
if ((call RouteSelect.selectRoute(pMsg,id)) != SUCCESS)
return pNewBuf;
// Failures at the send level do not cause the seq. number space to be
// rolled back properly. This is somewhat broken.
if (call SendMsg.send[id](pMsg->addr,pMsg->length,pMsg) == SUCCESS) {
pNewBuf = FwdBufList[iFwdBufHead];
FwdBufList[iFwdBufHead] = pMsg;
iFwdBufHead++; iFwdBufHead %= FWD_QUEUE_SIZE;
}
return pNewBuf;
}
event TOS_MsgPtr ReceiveMsg.receive[uint8_t id](TOS_MsgPtr pMsg) {
TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)pMsg->data;
uint16_t PayloadLen = pMsg->length - offsetof(TOS_MHopMsg,data);
#if 0
dbg(DBG_ROUTE, "MHop: Msg Rcvd, src 0x%02x, org 0x%02x, parent 0x%02x\n",
pMHMsg->sourceaddr, pMHMsg->originaddr, 0 /*pMHMsg->parentaddr*/);
#endif
// Ordinary message requiring forwarding
if (pMsg->addr == TOS_LOCAL_ADDRESS) { // Addressed to local node
if ((signal Intercept.intercept[id](pMsg,&pMHMsg->data[0],PayloadLen)) == SUCCESS) {
pMsg = mForward(pMsg,id);
}
}
else {
// Snoop the packet for permiscuous applications
signal Snoop.intercept[id](pMsg,&pMHMsg->data[0],PayloadLen);
}
return pMsg;
}
event result_t SendMsg.sendDone[uint8_t id](TOS_MsgPtr pMsg, result_t success) {
//dbg(DBG_ROUTE, "MHop: senddone 0x%x 0x%x\n", pMsg, success);
if (pMsg == FwdBufList[iFwdBufTail]) { // Msg was from forwarding queue
iFwdBufTail++; iFwdBufTail %= FWD_QUEUE_SIZE;
} else {
signal Send.sendDone[id](pMsg, success);
}
return SUCCESS;
}
command uint16_t RouteControl.getParent() {
return call RouteSelectCntl.getParent();
}
command uint8_t RouteControl.getQuality() {
return call RouteSelectCntl.getQuality();
}
command uint8_t RouteControl.getDepth() {
return call RouteSelectCntl.getDepth();
}
command uint8_t RouteControl.getOccupancy() {
uint16_t uiOutstanding = (uint16_t)iFwdBufTail - (uint16_t)iFwdBufHead;
uiOutstanding %= FWD_QUEUE_SIZE;
return (uint8_t)uiOutstanding;
}
command uint16_t RouteControl.getSender(TOS_MsgPtr msg) {
TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)msg->data;
return pMHMsg->sourceaddr;
}
command result_t RouteControl.setUpdateInterval(uint16_t Interval) {
return call RouteSelectCntl.setUpdateInterval(Interval);
}
command result_t RouteControl.manualUpdate() {
return call RouteSelectCntl.manualUpdate();
}
default event result_t Send.sendDone[uint8_t id](TOS_MsgPtr pMsg, result_t success) {
return SUCCESS;
}
default event result_t Intercept.intercept[uint8_t id](TOS_MsgPtr pMsg, void* payload,
uint16_t payloadLen) {
return SUCCESS;
}
default event result_t Snoop.intercept[uint8_t id](TOS_MsgPtr pMsg, void* payload,
uint16_t payloadLen) {
return SUCCESS;
}
}
--- NEW FILE: MultiHopWMEWMA.nc ---
// $Id: MultiHopWMEWMA.nc,v 1.1 2006/06/20 22:05:56 binetude Exp $
/* tab:4
* "Copyright (c) 2000-2003 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."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/*
*
* Authors: Philip Buonadonna, Alec Woo, Terence Tong, Crossbow
* Date last modified: 2/20/03
*
*/
includes AM;
includes MultiHop;
//#define MULTI_HOP_DEBUG 1
module MultiHopWMEWMA {
provides {
interface StdControl;
interface RouteSelect;
interface RouteControl;
interface FixRoute;
}
uses {
interface Leds;
interface Timer;
interface Timer as ATimer;
interface ReceiveMsg;
interface Intercept as Snoop[uint8_t id];
interface SendMsg;
interface Send as DebugSendMsg;
#ifdef USE_WATCHDOG
interface StdControl as PoochHandler;
interface WDT;
#endif
}
}
implementation {
enum {
NBRFLAG_VALID = 0x01,
NBRFLAG_NEW = 0x02,
NBRFLAG_EST_INIT = 0x04
};
enum {
BASE_STATION_ADDRESS = 0,
ROUTE_TABLE_SIZE = 16,
ESTIMATE_TO_ROUTE_RATIO = 10,
ACCEPTABLE_MISSED = -20,
DATA_TO_ROUTE_RATIO = 1,
DATA_FREQ = 8192,
SWITCH_THRESHOLD = 384,
MAX_ALLOWABLE_LINK_COST = 256*6,
LIVELINESS = 5,
MAX_DESCENDANT_LIVE = 5
};
enum {
ROUTE_INVALID = 0xff
};
struct SortEntry {
uint16_t id;
uint8_t receiveEst;
};
struct SortDbgEntry {
uint16_t id;
uint8_t sendEst;
uint8_t hopcount;
};
typedef struct RPEstEntry {
uint16_t id;
uint8_t receiveEst;
} __attribute__ ((packed)) RPEstEntry;
typedef struct RoutePacket {
uint16_t parent;
uint16_t cost;
uint8_t estEntries;
RPEstEntry estList[1];
} __attribute__ ((packed)) RoutePacket;
typedef struct TableEntry {
uint16_t id; // Node Address
uint16_t parent;
uint16_t cost;
uint8_t childLiveliness;
uint16_t missed;
uint16_t received;
int16_t lastSeqno;
uint8_t flags;
uint8_t liveliness;
uint8_t hop;
uint8_t receiveEst;
uint8_t sendEst;
} TableEntry;
TOS_Msg debugMsg;
TOS_Msg routeMsg;
bool gfSendRouteBusy;
bool gSelfTimer;
TableEntry BaseStation;
TableEntry NeighborTbl[ROUTE_TABLE_SIZE];
TableEntry *gpCurrentParent;
uint8_t gbCurrentHopCount;
uint16_t gbCurrentCost;
int16_t gCurrentSeqNo;
uint16_t gwEstTicks;
uint32_t gUpdateInterval;
bool fixedRoute;
uint16_t fixedParent;
uint8_t fixedDepth;
/*////////////////////////////////////////////////////////*/
/**
* Return index into neighbor table of the given node addr
* @author terence
* @param id
* @return index, if not found return ROUTE_INVALID
*/
uint8_t findEntry(uint16_t id) {
uint8_t i = 0;
for (i = 0; i < ROUTE_TABLE_SIZE; i++) {
if ((NeighborTbl[i].flags & NBRFLAG_VALID) && NeighborTbl[i].id == id) {
return i;
}
}
return ROUTE_INVALID;
}
/*////////////////////////////////////////////////////////*/
/**
* This function determines which entry should be replace
* in this case, we find the one with the lease send estimate
* @author terence
* @param void
* @return index of the table
*/
uint8_t findEntryToBeReplaced() {
uint8_t i = 0;
uint8_t minSendEst = -1;
uint8_t minSendEstIndex = ROUTE_INVALID;
for (i = 0; i < ROUTE_TABLE_SIZE; i++) {
if ((NeighborTbl[i].flags & NBRFLAG_VALID) == 0) {
return i;
}
if (minSendEst >= NeighborTbl[i].sendEst) {
minSendEst = NeighborTbl[i].sendEst;
minSendEstIndex = i;
}
}
return minSendEstIndex;
}
/*////////////////////////////////////////////////////////*/
/**
* This is going to make a new entry give an index and a id
* @author terence
* @param index, the index of the table
* @param id, the node id
* @return void
*/
void newEntry(uint8_t indes, uint16_t id) {
NeighborTbl[indes].id = id;
NeighborTbl[indes].flags = (NBRFLAG_VALID | NBRFLAG_NEW);
NeighborTbl[indes].liveliness = 0;
NeighborTbl[indes].parent = ROUTE_INVALID;
NeighborTbl[indes].cost = ROUTE_INVALID;
NeighborTbl[indes].childLiveliness = 0;
NeighborTbl[indes].hop = ROUTE_INVALID;
NeighborTbl[indes].missed = 0;
NeighborTbl[indes].received = 0;
NeighborTbl[indes].receiveEst = 0;
NeighborTbl[indes].sendEst = 0;
//call Estimator.clearTrackInfo(NeighborTbl[indes].trackInfo);
}
/*////////////////////////////////////////////////////////*/
/**
* Get neighbor table entry corresponding to the given address.
* If current entry doesn't exist, then create one, possibly
* evicting a previous entry.
* XXX - what if it evicts the parent???
*
* @author terence
* @param id, node id
* @return index
*/
uint8_t findPreparedIndex(uint16_t id) {
uint8_t indes = findEntry(id);
if (indes == (uint8_t) ROUTE_INVALID) {
indes = findEntryToBeReplaced();
newEntry(indes, id);
}
return indes;
}
int sortByReceiveEstFcn(const void *x, const void *y) {
struct SortEntry *nx = (struct SortEntry *) x;
struct SortEntry *ny = (struct SortEntry *) y;
uint8_t xReceiveEst = nx->receiveEst, yReceiveEst = ny->receiveEst;
if (xReceiveEst > yReceiveEst) return -1;
if (xReceiveEst == yReceiveEst) return 0;
if (xReceiveEst < yReceiveEst) return 1;
return 0; // shouldn't reach here becasue it covers all the cases
}
int sortDebugEstFcn(const void *x, const void *y) {
struct SortDbgEntry *nx = (struct SortDbgEntry *) x;
struct SortDbgEntry *ny = (struct SortDbgEntry *) y;
uint8_t xReceiveEst = nx->sendEst, yReceiveEst = ny->sendEst;
if (xReceiveEst > yReceiveEst) return -1;
if (xReceiveEst == yReceiveEst) return 0;
if (xReceiveEst < yReceiveEst) return 1;
return 0; // shouldn't reach here becasue it covers all the cases
}
uint32_t evaluateCost(uint16_t cost, uint8_t sendEst, uint8_t receiveEst) {
uint32_t transEst = (uint32_t) sendEst * (uint32_t) receiveEst;
uint32_t immed = ((uint32_t) 1 << 24);
if (transEst == 0) return ((uint32_t) 1 << (uint32_t) 16);
// DO NOT change this LINE! mica compiler is WEIRD!
immed = immed / transEst;
immed += ((uint32_t) cost << 6);
return immed;
}
void updateEst(TableEntry *Nbr) {
uint16_t usExpTotal, usActTotal, newAve;
if (Nbr->flags & NBRFLAG_NEW)
return;
usExpTotal = ESTIMATE_TO_ROUTE_RATIO;
//if (pNbr->hop != 0) {
// usExpTotal *= (1 + DATA_TO_ROUTE_RATIO);
//}
dbg(DBG_ROUTE,"MultiHopWMEWMA: Updating Nbr %d. ExpTotl = %d, rcvd= %d, missed = %d\n",
Nbr->id, usExpTotal, Nbr->received, Nbr->missed);
atomic {
usActTotal = Nbr->received + Nbr->missed;
if (usActTotal < usExpTotal) {
usActTotal = usExpTotal;
}
newAve = ((uint16_t) 255 * (uint16_t)Nbr->received) / (uint16_t)usActTotal;
Nbr->missed = 0;
Nbr->received = 0;
// If we haven't seen a recieveEst for us from our neighbor, decay our sendEst
// exponentially
if (Nbr->liveliness == 0) {
Nbr->sendEst >>= 1;
}else{
Nbr->liveliness --;
}
}
if (Nbr->flags & NBRFLAG_EST_INIT) {
uint16_t tmp;
tmp = ((2 * ((uint16_t)Nbr->receiveEst) + (uint16_t)newAve * 6) / 8);
Nbr->receiveEst = (uint8_t)tmp;
}
else {
Nbr->receiveEst = (uint8_t) newAve;
Nbr->flags ^= NBRFLAG_EST_INIT;
}
if(Nbr->childLiveliness > 0) Nbr->childLiveliness --;
}
void updateTable() {
TableEntry *pNbr;
uint8_t i = 0;
gwEstTicks++;
gwEstTicks %= ESTIMATE_TO_ROUTE_RATIO;
for(i = 0; i < ROUTE_TABLE_SIZE; i++) {
pNbr = &NeighborTbl[i];
if (pNbr->flags & NBRFLAG_VALID) {
if (gwEstTicks == 0)
updateEst(pNbr);
}
}
}
bool updateNbrCounters(uint16_t saddr, int16_t seqno, uint8_t *NbrIndex) {
TableEntry *pNbr;
int16_t sDelta;
uint8_t iNbr;
bool Result = FALSE; // Result is TRUE if message is a duplicate
iNbr = findPreparedIndex(saddr);
pNbr = &NeighborTbl[iNbr];
sDelta = (seqno - NeighborTbl[iNbr].lastSeqno - 1);
if (pNbr->flags & NBRFLAG_NEW) {
pNbr->received++;
pNbr->lastSeqno = seqno;
pNbr->flags ^= NBRFLAG_NEW;
}
else if (sDelta >= 0) {
pNbr->missed += sDelta;
pNbr->received++;
pNbr->lastSeqno = seqno;
}
else if (sDelta < ACCEPTABLE_MISSED) {
// Something happend to this node. Reinitialize it's state
newEntry(iNbr,saddr);
pNbr->received++;
pNbr->lastSeqno = seqno;
pNbr->flags ^= NBRFLAG_NEW;
}
else {
Result = TRUE;
}
*NbrIndex = iNbr;
return Result;
}
void chooseParent() {
TableEntry *pNbr;
uint32_t ulNbrLinkCost = (uint32_t) -1;
uint32_t ulNbrTotalCost = (uint32_t) -1;
uint32_t oldParentCost = (uint32_t) -1;
uint32_t oldParentLinkCost = (uint32_t) -1;
uint32_t ulMinTotalCost = (uint32_t) -1;
TableEntry* pNewParent = NULL;
TableEntry* pOldParent = NULL;
uint8_t i;
if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) return;
// Choose the parent based on minimal hopcount and cost.
// There is a special case for choosing a base-station as it's
// receiveEst may be zero (it's not sending any packets)
for (i = 0;i < ROUTE_TABLE_SIZE;i++) {
pNbr = &NeighborTbl[i];
if (!(pNbr->flags & NBRFLAG_VALID)) continue;
if (pNbr->parent == TOS_LOCAL_ADDRESS) continue;
if (pNbr->parent == ROUTE_INVALID) continue;
if (pNbr->hop == ROUTE_INVALID) continue;
if (pNbr->cost == (uint16_t) ROUTE_INVALID) continue;
if (pNbr->sendEst < 25 || pNbr->receiveEst < 25) continue;
if (pNbr->childLiveliness > 0) continue;
ulNbrLinkCost = evaluateCost(0, pNbr->sendEst,pNbr->receiveEst);
ulNbrTotalCost = evaluateCost(pNbr->cost, pNbr->sendEst,pNbr->receiveEst);
call Leds.greenToggle();
if (ulNbrLinkCost > MAX_ALLOWABLE_LINK_COST) continue;
dbg(DBG_ROUTE,"MultiHopWMEWMA node: %d, Cost %d, link Cost, %d\n", pNbr->id, ulNbrTotalCost, ulNbrLinkCost);
if (pNbr == gpCurrentParent) {
pOldParent = pNbr;
oldParentCost = ulNbrTotalCost;
oldParentLinkCost = ulNbrLinkCost;
continue;
}
if (ulMinTotalCost > ulNbrTotalCost) {
ulMinTotalCost = ulNbrTotalCost;
pNewParent = pNbr;
}
}
//now pick between old and new.
if(pNewParent == NULL) {
//use the old parent unless it is null;
pNewParent = pOldParent;
ulMinTotalCost = oldParentCost;
} else if((pOldParent != NULL) &&
(oldParentCost < (SWITCH_THRESHOLD + ulMinTotalCost))){
//both valid, but use the old parent
pNewParent = pOldParent;
ulMinTotalCost = oldParentCost;
}
if (pNewParent) {
atomic {
gpCurrentParent = pNewParent;
gbCurrentHopCount = pNewParent->hop + 1;
gbCurrentCost = ulMinTotalCost >> 6;
}
} else {
atomic {
gpCurrentParent = NULL;
gbCurrentHopCount = ROUTE_INVALID;
gbCurrentCost = ROUTE_INVALID;
}
}
}
uint8_t last_entry_sent;
task void SendRouteTask() {
TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *) &routeMsg.data[0];
RoutePacket *pRP = (RoutePacket *)&pMHMsg->data[0];
uint8_t length = offsetof(TOS_MHopMsg,data) + offsetof(RoutePacket,estList);
uint8_t maxEstEntries;
uint8_t i,j;
uint8_t last_index_added = 0;
if (gfSendRouteBusy) {
return;
}
dbg(DBG_ROUTE,"MultiHopWMEWMA Sending route update msg.\n");
dbg(DBG_ROUTE,"Current cost: %d.\n", gbCurrentCost);
maxEstEntries = TOSH_DATA_LENGTH - length;
maxEstEntries = maxEstEntries / sizeof(RPEstEntry);
pRP->parent = (gpCurrentParent) ? gpCurrentParent->id : ROUTE_INVALID;
pRP->cost = gbCurrentCost;
for (i = 0,j = 0;i < ROUTE_TABLE_SIZE && j < maxEstEntries; i++) {
uint8_t table_index = i + last_entry_sent + 1;
if(table_index >= ROUTE_TABLE_SIZE) table_index -=ROUTE_TABLE_SIZE;
if (NeighborTbl[table_index].flags & NBRFLAG_VALID && NeighborTbl[table_index].receiveEst > 100) {
pRP->estList[j].id = NeighborTbl[table_index].id;
pRP->estList[j].receiveEst = NeighborTbl[table_index].receiveEst;
j ++;
length += sizeof(RPEstEntry);
last_index_added = table_index;
dbg(DBG_ROUTE,"Adding %d to route msg.\n", pRP->estList[j].id);
}
}
last_entry_sent = last_index_added;
dbg(DBG_ROUTE,"Added total of %d entries to route msg.\n", j);
pRP->estEntries = j;
pMHMsg->sourceaddr = pMHMsg->originaddr = TOS_LOCAL_ADDRESS;
pMHMsg->hopcount = gbCurrentHopCount;
pMHMsg->seqno = gCurrentSeqNo++;
if (call SendMsg.send(TOS_BCAST_ADDR, length, &routeMsg) == SUCCESS) {
gfSendRouteBusy = TRUE;
}
}
#ifdef MULTI_HOP_DEBUG
task void SendDebugTask() {
struct SortDbgEntry sortTbl[ROUTE_TABLE_SIZE];
uint16_t max_length;
uint8_t length = offsetof(DebugPacket,estList);
DebugPacket *pRP = (DebugPacket *)call DebugSendMsg.getBuffer(&debugMsg,&max_length);
uint8_t maxEstEntries;
uint16_t parent;
uint8_t i,j;
dbg(DBG_ROUTE,"MultiHopWMEWMA Sending route debug msg.\n");
maxEstEntries = max_length / sizeof(DBGEstEntry);
maxEstEntries --;
parent = (gpCurrentParent) ? gpCurrentParent->id : ROUTE_INVALID;
for (i = 0,j = 0;i < ROUTE_TABLE_SIZE; i++) {
if (NeighborTbl[i].flags & NBRFLAG_VALID && NeighborTbl[i].id != parent) {
sortTbl[j].id = NeighborTbl[i].id;
sortTbl[j].sendEst = NeighborTbl[i].sendEst;
sortTbl[j].hopcount = NeighborTbl[i].hop;
j++;
}
}
qsort (sortTbl,j,sizeof(struct SortDbgEntry),sortDebugEstFcn);
pRP->estEntries = (j > maxEstEntries) ? maxEstEntries : j;
pRP->estList[0].id = parent;
if(gpCurrentParent){
pRP->estList[0].sendEst = gpCurrentParent->sendEst;
pRP->estList[0].hopcount = gpCurrentParent->hop;
}
length += sizeof(DBGEstEntry);
for (i = 0; i < pRP->estEntries; i++) {
pRP->estList[i+1].id = sortTbl[i].id;
pRP->estList[i+1].sendEst = sortTbl[i].sendEst;
pRP->estList[i+1].hopcount = sortTbl[i].hopcount;
length += sizeof(DBGEstEntry);
}
pRP->estEntries ++;
call DebugSendMsg.send(&debugMsg, length);
}
int debugCounter;
#endif
task void TimerTask() {
call Leds.redToggle();
dbg(DBG_ROUTE,"MultiHopWMEWMA timer task.\n");
updateTable();
#ifndef NDEBUG
{
int i;
dbg(DBG_ROUTE,"\taddr\tprnt\tcost\tmisd\trcvd\tlstS\thop\trEst\tsEst\tDesc\n");
for (i = 0;i < ROUTE_TABLE_SIZE;i++) {
if (NeighborTbl[i].flags) {
dbg(DBG_ROUTE,"\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
NeighborTbl[i].id,
NeighborTbl[i].parent,
NeighborTbl[i].cost,
NeighborTbl[i].missed,
NeighborTbl[i].received,
NeighborTbl[i].lastSeqno,
NeighborTbl[i].hop,
NeighborTbl[i].receiveEst,
NeighborTbl[i].sendEst,
NeighborTbl[i].childLiveliness);
}
}
if (gpCurrentParent) {
dbg(DBG_ROUTE,"MultiHopWMEWMA: Parent = %d\n",gpCurrentParent->id);
}
}
#endif
chooseParent();
#ifdef MULTI_HOP_DEBUG
if(TOS_LOCAL_ADDRESS != BASE_STATION_ADDRESS) debugCounter ++;
if(debugCounter > 1){
post SendDebugTask();
debugCounter = 0;
}else{
#endif //MULTI_HOP_DEBUG
call ATimer.start(TIMER_ONE_SHOT, 32);
//post SendRouteTask();
#ifdef MULTI_HOP_DEBUG
}
#endif //MULTI_HOP_DEBUG
}
event result_t ATimer.fired(){
post SendRouteTask();
return SUCCESS;
}
command result_t StdControl.init() {
memset((void *)NeighborTbl,0,(sizeof(TableEntry) * ROUTE_TABLE_SIZE));
BaseStation.id = TOS_UART_ADDR;
BaseStation.parent = TOS_UART_ADDR;
BaseStation.flags = NBRFLAG_VALID;
BaseStation.hop = 0;
gpCurrentParent = NULL;
gbCurrentHopCount = ROUTE_INVALID;
gCurrentSeqNo = 0;
gwEstTicks = 0;
gUpdateInterval = DATA_TO_ROUTE_RATIO * DATA_FREQ;
gfSendRouteBusy = FALSE;
gSelfTimer = TRUE;
fixedRoute = FALSE;
if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) {
gpCurrentParent = &BaseStation;
gbCurrentHopCount = 0;
gbCurrentCost = 0;
}
return SUCCESS;
}
command result_t StdControl.start() {
if (gSelfTimer){
post TimerTask();
call Timer.start(TIMER_REPEAT,gUpdateInterval);
#ifdef USE_WATCHDOG
call PoochHandler.start();
call WDT.start(gUpdateInterval * 5);
#endif
}
// post TimerTask();
// call Timer.start(TIMER_REPEAT,gUpdateInterval);
//}
//call Leds.redToggle();
return SUCCESS;
}
command result_t StdControl.stop() {
call Timer.stop();
return SUCCESS;
}
command bool RouteSelect.isActive() {
#if 0
bool Result = FALSE;
if (gpCurrentParent != NULL) {
Result = TRUE;
}
return Result;
#endif
return TRUE;
}
void updateDescendant(uint16_t id){
uint8_t indes = findEntry(id);
if (indes == (uint8_t) ROUTE_INVALID) { return;}
else{
NeighborTbl[indes].childLiveliness = MAX_DESCENDANT_LIVE;
}
}
command result_t RouteSelect.selectRoute(TOS_MsgPtr Msg, uint8_t id) {
TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
uint8_t iNbr;
bool fIsDuplicate;
result_t Result = SUCCESS;
if (!fixedRoute && (gpCurrentParent == NULL)) {
// If the msg is locally generated, then send it to the broadcast address
// This is necessary to seed the network.
if ((pMHMsg->sourceaddr == TOS_LOCAL_ADDRESS) &&
(pMHMsg->originaddr == TOS_LOCAL_ADDRESS)) {
pMHMsg->sourceaddr = TOS_LOCAL_ADDRESS;
pMHMsg->hopcount = fixedRoute ? fixedDepth : gbCurrentHopCount;
pMHMsg->seqno = gCurrentSeqNo++;
Msg->addr = TOS_BCAST_ADDR;
return SUCCESS;
}
else {
return FAIL;
}
}
if (((!fixedRoute) && (gbCurrentHopCount >= pMHMsg->hopcount))
||((fixedRoute) && (fixedDepth >= pMHMsg->hopcount))) {
// Possible cycle??
return FAIL;
}
if ((pMHMsg->sourceaddr == TOS_LOCAL_ADDRESS) &&
(pMHMsg->originaddr == TOS_LOCAL_ADDRESS)) {
fIsDuplicate = FALSE;
}
else {
fIsDuplicate = updateNbrCounters(pMHMsg->sourceaddr,pMHMsg->seqno,&iNbr);
}
if (!fIsDuplicate) {
pMHMsg->sourceaddr = TOS_LOCAL_ADDRESS;
pMHMsg->hopcount = fixedRoute ? fixedDepth : gbCurrentHopCount;
if ((!fixedRoute && (gpCurrentParent->id != TOS_UART_ADDR))
|| (fixedRoute && (fixedParent != TOS_UART_ADDR))) {
pMHMsg->seqno = gCurrentSeqNo++;
}
Msg->addr = fixedRoute ? fixedParent : gpCurrentParent->id;
if(pMHMsg->originaddr != TOS_LOCAL_ADDRESS){
updateDescendant(pMHMsg->originaddr);
}
}
else {
Result = FAIL;
}
dbg(DBG_ROUTE,"MultiHopWMEWMA: Sequence Number: %d\n", pMHMsg->seqno);
return Result;
}
command result_t RouteSelect.initializeFields(TOS_MsgPtr Msg, uint8_t id) {
TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
pMHMsg->sourceaddr = pMHMsg->originaddr = TOS_LOCAL_ADDRESS;
pMHMsg->hopcount = ROUTE_INVALID;
return SUCCESS;
}
command uint8_t* RouteSelect.getBuffer(TOS_MsgPtr Msg, uint16_t* Len) {
}
command uint16_t FixRoute.getParent() {
uint16_t addr;
addr = (gpCurrentParent != NULL) ? gpCurrentParent->id : 0xffff;
return addr;
}
command uint16_t RouteControl.getParent() {
return fixedRoute ? fixedParent : call FixRoute.getParent();
}
command uint8_t RouteControl.getQuality() {
uint8_t val;
val = (gpCurrentParent != NULL) ? gpCurrentParent->sendEst : 0x00;
return val;
}
command uint8_t FixRoute.getDepth() {
return gbCurrentHopCount;
}
command uint8_t RouteControl.getDepth() {
return fixedRoute ? fixedDepth : call FixRoute.getDepth();
}
command uint8_t RouteControl.getOccupancy() {
return 0;
}
command uint16_t RouteControl.getSender(TOS_MsgPtr msg) {
TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)msg->data;
return pMHMsg->sourceaddr;
}
command result_t RouteControl.setUpdateInterval(uint16_t Interval) {
result_t Result;
call Timer.stop();
gUpdateInterval = (Interval * 1024L); // * 1024 to make the math simpler
gSelfTimer = TRUE;
Result = call Timer.start(TIMER_REPEAT,gUpdateInterval);
#ifdef USE_WATCHDOG
call PoochHandler.stop();
call PoochHandler.start();
call WDT.start(gUpdateInterval * 5);
#endif
return Result;
}
command result_t RouteControl.manualUpdate() {
result_t Result;
gSelfTimer = FALSE;
call Timer.stop();
Result = post TimerTask();
return Result;
}
event result_t Timer.fired() {
post TimerTask();
return SUCCESS;
}
event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr Msg) {
TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
RoutePacket *pRP = (RoutePacket *)&pMHMsg->data[0];
uint16_t saddr;
uint8_t i, iNbr;
call Leds.yellowToggle();
#ifdef USE_WATCHDOG
call WDT.reset();
#endif
saddr = pMHMsg->sourceaddr;
updateNbrCounters(saddr,pMHMsg->seqno,&iNbr);
// iNbr = findPreparedIndex(saddr);
NeighborTbl[iNbr].parent = pRP->parent;
NeighborTbl[iNbr].hop = pMHMsg->hopcount;
NeighborTbl[iNbr].cost = pRP->cost;
// If it is no longer my child, clear it
if (NeighborTbl[iNbr].childLiveliness > 0 && pRP->parent != TOS_LOCAL_ADDRESS)
NeighborTbl[iNbr].childLiveliness = 0;
// find out my address, extract the estimation
for (i = 0; i < pRP->estEntries; i++) {
if (pRP->estList[i].id == TOS_LOCAL_ADDRESS) {
NeighborTbl[iNbr].sendEst = pRP->estList[i].receiveEst;
NeighborTbl[iNbr].liveliness = LIVELINESS;
}
}
return Msg;
}
event result_t Snoop.intercept[uint8_t id](TOS_MsgPtr Msg, void *Payload, uint16_t Len) {
TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
uint8_t iNbr;
updateNbrCounters(pMHMsg->sourceaddr,pMHMsg->seqno,&iNbr);
// Extract routing information if we know this is a multihop message
// Something in the future.
return SUCCESS;
}
event result_t SendMsg.sendDone(TOS_MsgPtr pMsg, result_t success) {
gfSendRouteBusy = FALSE;
return SUCCESS;
}
event result_t DebugSendMsg.sendDone(TOS_MsgPtr pMsg, result_t success) {
return SUCCESS;
}
command result_t FixRoute.fix() {
if (fixedRoute) return SUCCESS;
fixedRoute = TRUE;
fixedParent = gpCurrentParent->id;
fixedDepth = gbCurrentHopCount;
return SUCCESS;
}
command result_t FixRoute.release() {
fixedRoute = FALSE;
return SUCCESS;
}
command uint8_t FixRoute.getFixedRoute() {
return fixedRoute ? 1 : 0;
}
}
--- NEW FILE: README ---
# Please contact tinyos-help at millennium.berkeley.edu for
# questions or bug reports. Any other suggestions or feedback
# can be sent to us:
# Philip Buonadonna (pbuonado at intel-research.net) or
# Alec Woo (awoo at cs.berkeley.edu)
# November 20th, 2003.
Important parameters to tune in MultihopWMEWMA.nc
BASE_STATION_ADDRESS = 0,
ROUTE_TABLE_SIZE = 16,
ESTIMATE_TO_ROUTE_RATIO = 10,
DATA_TO_ROUTE_RATIO = 2,
DATA_FREQ = 10000,
SWITCH_THRESHOLD = 192,
MAX_DESCENDANT = 5
In this protocol, the minimum message rate is defined by route message
rate, which is a ratio of the data rate defined by
DATA_TO_ROUTE_RATIO. For example, if DATA_FREQ is 10000 (~ 1
packet/10 sec) and DATA_TO_ROUTE_RATIO is 2, the route message
is will be 20000 (~ 1 msg/20sec). This rate is tunable and
will affect network load and rate of adaptation to changes.
ESTIMATE_TO_ROUTE is a parameter that defines the time window
T for WMEWMA estimator. If it is set to 10, it means that
an estimation will be performed every ten route message time.
SWITCH_THRESHOLD is a parameter to define a noise margin for
switching to a better parent. It is a scaled value. To convert
it to the number of transmission, simply divide it by 256.
In this case, 192/256 = 0.75. That is, we only switch to a
new parent if its cost is 0.75 lower than our current parent.
MAX_DESCENDADNT_LIVE is used as a paremter to time out children
in the neighbor table. 5 means a child
Notice that chooseParent() is called on a periodic basis as
a route damping mechanism. The period is the same as the
route message rate.
The current route table managment is a simple filtering
mechanism based on send (outbound) link estimations.
--- NEW FILE: WMEWMAMultiHopRouter.nc ---
includes MultiHop;
configuration WMEWMAMultiHopRouter {
provides {
interface StdControl;
// The interface are as parameterised by the active message id
// only the 10 active message ids defined MultiHop.h are supported.
interface Receive[uint8_t id];
interface Intercept[uint8_t id];
interface Intercept as Snoop[uint8_t id];
interface Send[uint8_t id];
interface RouteControl;
}
uses {
interface ReceiveMsg[uint8_t id];
}
}
implementation {
// Uncomment for use with mh6
components MultiHopEngineM, MultiHopWMEWMA, GenericCommPromiscuous as Comm,
QueuedSend, TimerC,
#ifdef USE_WATCHDOG
WDTC,
#endif
NoLeds;
StdControl = MultiHopEngineM;
Receive = MultiHopEngineM;
Send = MultiHopEngineM;
Intercept = MultiHopEngineM.Intercept;
Snoop = MultiHopEngineM.Snoop;
RouteControl = MultiHopEngineM;
ReceiveMsg = MultiHopEngineM;
MultiHopEngineM.SubControl -> QueuedSend.StdControl;
MultiHopEngineM.SubControl -> MultiHopWMEWMA.StdControl;
MultiHopEngineM.CommStdControl -> Comm;
MultiHopEngineM.CommControl -> Comm;
MultiHopEngineM.RouteSelectCntl -> MultiHopWMEWMA.RouteControl;
MultiHopEngineM.RouteSelect -> MultiHopWMEWMA;
MultiHopEngineM.SendMsg -> QueuedSend.SendMsg;
MultiHopWMEWMA.Timer -> TimerC.Timer[unique("Timer")];
MultiHopWMEWMA.ATimer -> TimerC.Timer[unique("Timer")];
MultiHopWMEWMA.ReceiveMsg -> Comm.ReceiveMsg[AM_MULTIHOPMSG];
MultiHopWMEWMA.Snoop -> MultiHopEngineM.Snoop;
MultiHopWMEWMA.SendMsg -> QueuedSend.SendMsg[AM_MULTIHOPMSG];
MultiHopWMEWMA.DebugSendMsg -> MultiHopEngineM.Send[3];
MultiHopEngineM.ReceiveMsg[3] -> Comm.ReceiveMsg[3];
MultiHopWMEWMA.Leds -> NoLeds;
#ifdef USE_WATCHDOG
MultiHopWMEWMA.PoochHandler -> WDTC.StdControl;
MultiHopWMEWMA.WDT -> WDTC.WDT;
#endif
}
More information about the Tinyos-contrib-commits
mailing list