📄 ctproutingenginep.nc
字号:
command void CtpInfo.triggerRouteUpdate() {
resetInterval();
}
command void CtpInfo.triggerImmediateRouteUpdate() {
resetInterval();
}
command void CtpInfo.setNeighborCongested(am_addr_t n, bool congested) {
uint8_t idx;
if (ECNOff)
return;
idx = routingTableFind(n);
if (idx < routingTableActive) {
routingTable[idx].info.congested = congested;
}
if (routeInfo.congested && !congested)
post updateRouteTask();
else if (routeInfo.parent == n && congested)
post updateRouteTask();
}
command bool CtpInfo.isNeighborCongested(am_addr_t n) {
uint8_t idx;
if (ECNOff)
return FALSE;
idx = routingTableFind(n);
if (idx < routingTableActive) {
return routingTable[idx].info.congested;
}
return FALSE;
}
/* RootControl interface */
/** sets the current node as a root, if not already a root */
/* returns FAIL if it's not possible for some reason */
command error_t RootControl.setRoot() {
bool route_found = FALSE;
route_found = (routeInfo.parent == INVALID_ADDR);
atomic {
state_is_root = 1;
routeInfo.parent = my_ll_addr; //myself
routeInfo.etx = 0;
}
if (route_found)
signal Routing.routeFound();
dbg("TreeRouting","%s I'm a root now!\n",__FUNCTION__);
call CollectionDebug.logEventRoute(NET_C_TREE_NEW_PARENT, routeInfo.parent, 0, routeInfo.etx);
return SUCCESS;
}
command error_t RootControl.unsetRoot() {
atomic {
state_is_root = 0;
routeInfoInit(&routeInfo);
}
dbg("TreeRouting","%s I'm not a root now!\n",__FUNCTION__);
post updateRouteTask();
return SUCCESS;
}
command bool RootControl.isRoot() {
return state_is_root;
}
default event void Routing.noRoute() {
}
default event void Routing.routeFound() {
}
/* The link will be recommended for insertion if it is better* than some
* link in the routing table that is not our parent.
* We are comparing the path quality up to the node, and ignoring the link
* quality from us to the node. This is because of a couple of things:
* 1. we expect this call only for links with white bit set
* 2. we are being optimistic to the nodes in the table, by ignoring the
* 1-hop quality to them (which means we are assuming it's 1 as well)
* This actually sets the bar a little higher for replacement
* 3. this is faster
*/
event bool CompareBit.shouldInsert(message_t *msg, void* payload, uint8_t len) {
bool found = FALSE;
uint16_t pathEtx;
uint16_t neighEtx;
int i;
routing_table_entry* entry;
ctp_routing_header_t* rcvBeacon;
if ((call AMPacket.type(msg) != AM_CTP_ROUTING) ||
(len != sizeof(ctp_routing_header_t)))
return FALSE;
/* 1.determine this packet's path quality */
rcvBeacon = (ctp_routing_header_t*)payload;
if (rcvBeacon->parent == INVALID_ADDR)
return FALSE;
/* the node is a root, recommend insertion! */
if (rcvBeacon->etx == 0) {
return TRUE;
}
pathEtx = rcvBeacon->etx; // + linkEtx;
/* 2. see if we find some neighbor that is worse */
for (i = 0; i < routingTableActive && !found; i++) {
entry = &routingTable[i];
//ignore parent, since we can't replace it
if (entry->neighbor == routeInfo.parent)
continue;
neighEtx = entry->info.etx;
//neighEtx = evaluateEtx(call LinkEstimator.getLinkQuality(entry->neighbor));
found |= (pathEtx < neighEtx);
}
return found;
}
/************************************************************/
/* Routing Table Functions */
/* The routing table keeps info about neighbor's route_info,
* and is used when choosing a parent.
* The table is simple:
* - not fragmented (all entries in 0..routingTableActive)
* - not ordered
* - no replacement: eviction follows the LinkEstimator table
*/
void routingTableInit() {
routingTableActive = 0;
}
/* Returns the index of parent in the table or
* routingTableActive if not found */
uint8_t routingTableFind(am_addr_t neighbor) {
uint8_t i;
if (neighbor == INVALID_ADDR)
return routingTableActive;
for (i = 0; i < routingTableActive; i++) {
if (routingTable[i].neighbor == neighbor)
break;
}
return i;
}
error_t routingTableUpdateEntry(am_addr_t from, am_addr_t parent, uint16_t etx) {
uint8_t idx;
uint16_t linkEtx;
linkEtx = evaluateEtx(call LinkEstimator.getLinkQuality(from));
idx = routingTableFind(from);
if (idx == routingTableSize) {
//not found and table is full
//if (passLinkEtxThreshold(linkEtx))
//TODO: add replacement here, replace the worst
//}
dbg("TreeRouting", "%s FAIL, table full\n", __FUNCTION__);
return FAIL;
}
else if (idx == routingTableActive) {
//not found and there is space
if (passLinkEtxThreshold(linkEtx)) {
atomic {
routingTable[idx].neighbor = from;
routingTable[idx].info.parent = parent;
routingTable[idx].info.etx = etx;
routingTable[idx].info.haveHeard = 1;
routingTable[idx].info.congested = FALSE;
routingTableActive++;
}
dbg("TreeRouting", "%s OK, new entry\n", __FUNCTION__);
} else {
dbg("TreeRouting", "%s Fail, link quality (%hu) below threshold\n", __FUNCTION__, linkEtx);
}
} else {
//found, just update
atomic {
routingTable[idx].neighbor = from;
routingTable[idx].info.parent = parent;
routingTable[idx].info.etx = etx;
routingTable[idx].info.haveHeard = 1;
}
dbg("TreeRouting", "%s OK, updated entry\n", __FUNCTION__);
}
return SUCCESS;
}
/* if this gets expensive, introduce indirection through an array of pointers */
error_t routingTableEvict(am_addr_t neighbor) {
uint8_t idx,i;
idx = routingTableFind(neighbor);
if (idx == routingTableActive)
return FAIL;
routingTableActive--;
for (i = idx; i < routingTableActive; i++) {
routingTable[i] = routingTable[i+1];
}
return SUCCESS;
}
/*********** end routing table functions ***************/
/* Default implementations for CollectionDebug calls.
* These allow CollectionDebug not to be wired to anything if debugging
* is not desired. */
default command error_t CollectionDebug.logEvent(uint8_t type) {
return SUCCESS;
}
default command error_t CollectionDebug.logEventSimple(uint8_t type, uint16_t arg) {
return SUCCESS;
}
default command error_t CollectionDebug.logEventDbg(uint8_t type, uint16_t arg1, uint16_t arg2, uint16_t arg3) {
return SUCCESS;
}
default command error_t CollectionDebug.logEventMsg(uint8_t type, uint16_t msg, am_addr_t origin, am_addr_t node) {
return SUCCESS;
}
default command error_t CollectionDebug.logEventRoute(uint8_t type, am_addr_t parent, uint8_t hopcount, uint16_t etx) {
return SUCCESS;
}
command bool CtpRoutingPacket.getOption(message_t* msg, ctp_options_t opt) {
return ((getHeader(msg)->options & opt) == opt) ? TRUE : FALSE;
}
command void CtpRoutingPacket.setOption(message_t* msg, ctp_options_t opt) {
getHeader(msg)->options |= opt;
}
command void CtpRoutingPacket.clearOption(message_t* msg, ctp_options_t opt) {
getHeader(msg)->options &= ~opt;
}
command void CtpRoutingPacket.clearOptions(message_t* msg) {
getHeader(msg)->options = 0;
}
command am_addr_t CtpRoutingPacket.getParent(message_t* msg) {
return getHeader(msg)->parent;
}
command void CtpRoutingPacket.setParent(message_t* msg, am_addr_t addr) {
getHeader(msg)->parent = addr;
}
command uint16_t CtpRoutingPacket.getEtx(message_t* msg) {
return getHeader(msg)->etx;
}
command void CtpRoutingPacket.setEtx(message_t* msg, uint16_t etx) {
getHeader(msg)->etx = etx;
}
command uint8_t CtpInfo.numNeighbors() {
return routingTableActive;
}
command uint16_t CtpInfo.getNeighborLinkQuality(uint8_t n) {
return (n < routingTableActive)? call LinkEstimator.getLinkQuality(routingTable[n].neighbor):0xffff;
}
command uint16_t CtpInfo.getNeighborRouteQuality(uint8_t n) {
return (n < routingTableActive)? call LinkEstimator.getLinkQuality(routingTable[n].neighbor) + routingTable[n].info.etx:0xfffff;
}
command am_addr_t CtpInfo.getNeighborAddr(uint8_t n) {
return (n < routingTableActive)? routingTable[n].neighbor:AM_BROADCAST_ADDR;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -