📄 ctproutingenginep.nc
字号:
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() { } /* This should see if the node should be inserted in the table. * If the white_bit is set, this means the LL believes this is a good * first hop link. * 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. because of the white bit, we assume that the 1-hop to the candidate * link is good (say, etx=1) * 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 * 4. it doesn't require the link estimator to have stabilized on a link */ event bool CompareBit.shouldInsert(message_t *msg, void* payload, uint8_t len, bool white_bit) { bool found = FALSE; uint16_t pathEtx; //uint16_t linkEtx = evaluateEtx(0); 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, uint8_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 + -