interface Receive as BeaconReceive;
interface LinkEstimator;
interface AMPacket;
- interface LinkSrcPacket;
interface SplitControl as RadioControl;
interface Timer<TMilli> as BeaconTimer;
interface Timer<TMilli> as RouteTimer;
command error_t Init.init() {
uint8_t maxLength;
- routeUpdateTimerCount = 0;
+ routeUpdateTimerCount = 0;
radioOn = FALSE;
running = FALSE;
parentChanges = 0;
routeInfoInit(&routeInfo);
routingTableInit();
my_ll_addr = call AMPacket.address();
- beaconMsg = call BeaconSend.getPayload(&beaconMsgBuffer);
+ 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);
/* 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 */
- /* TODO: take into account congested state to select parents */
task void updateRouteTask() {
uint8_t i;
routing_table_entry* entry;
}
continue;
}
+ /* Ignore links that are congested */
+ if (entry->info.congested)
+ continue;
/* Ignore links that are bad */
if (!passLinkEtxThreshold(linkEtx)) {
dbg("TreeRouting", " did not pass threshold.\n");
//call CollectionDebug.logEventDbg(NET_C_DBG_3, routeInfo.parent, currentEtx, minEtx);
/* Now choose between the current parent and the best neighbor */
+ /* Requires that:
+ 1. at least another neighbor was found with ok quality and not congested
+ 2. the current parent is congested and the other best route is at least as good
+ 3. or the current parent is not congested and the neighbor quality is better by
+ the PARENT_SWITCH_THRESHOLD.
+ Note: if our parent is congested, in order to avoid forming loops, we try to select
+ a node which is not a descendent of our parent. routeInfo.ext is our parent's
+ etx. Any descendent will be at least that + 10 (1 hop), so we restrict the
+ selection to be less than that.
+ */
if (minEtx != MAX_METRIC) {
if (currentEtx == MAX_METRIC ||
+ (routeInfo.congested && (minEtx < (routeInfo.etx + 10))) ||
minEtx + PARENT_SWITCH_THRESHOLD < currentEtx) {
// routeInfo.metric will not store the composed metric.
// since the linkMetric may change, we will compose whenever
ctp_routing_header_t* getHeader(message_t* m) {
- return (ctp_routing_header_t*)call BeaconReceive.getPayload(m, NULL);
+ return (ctp_routing_header_t*)call BeaconSend.getPayload(m, call BeaconSend.maxPayloadLength());
}
}
//need to get the am_addr_t of the source
- from = call LinkSrcPacket.getSrc(msg);
+ from = call AMPacket.source(msg);
rcvBeacon = (ctp_routing_header_t*)payload;
+
congested = call CtpRoutingPacket.getOption(msg, CTP_OPT_ECN);
dbg("TreeRouting","%s from: %d [ parent: %d etx: %d]\n",
command void CtpInfo.triggerRouteUpdate() {
// Random time in interval 64-127ms
- uint16_t time = call Random.rand16();
- time &= 0x3f;
- time += 64;
+ uint16_t beaconDelay = call Random.rand16();
+ beaconDelay &= 0x3f;
+ beaconDelay += 64;
if (call BeaconTimer.gett0() + call BeaconTimer.getdt() -
- call BeaconTimer.getNow() >= time) {
+ call BeaconTimer.getNow() >= beaconDelay) {
call BeaconTimer.stop();
- call BeaconTimer.startOneShot(time);
+ call BeaconTimer.startOneShot(beaconDelay);
}
}
command void CtpInfo.triggerImmediateRouteUpdate() {
// Random time in interval 4-11ms
- uint16_t time = call Random.rand16();
- time &= 0x7;
- time += 4;
+ uint16_t beaconDelay = call Random.rand16();
+ beaconDelay &= 0x7;
+ beaconDelay += 4;
call BeaconTimer.stop();
- call BeaconTimer.startOneShot(time);
+ call BeaconTimer.startOneShot(beaconDelay);
}
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;
}
- /* TODO: (this only makes sense if routeUpdateTask takes congestion into
- * account for selecting routes.)
- * if (routeInfo.congested && !congested)
- * post routeUpdateTask()
- * else if (routeInfo.parent == n && congested) {
- * post routeUpdateTask()
- *
- */
+ if (routeInfo.congested && !congested)
+ post updateRouteTask();
+ else if (routeInfo.parent == n && congested)
+ post updateRouteTask();
}
command bool CtpInfo.isNeighborCongested(am_addr_t n) {
routingTable[idx].neighbor = from;
routingTable[idx].info.parent = parent;
routingTable[idx].info.etx = etx;
- routingTable[idx].info.haveHeard = 1;
+ routingTable[idx].info.haveHeard = 1;
+ routingTable[idx].info.congested = FALSE;
routingTableActive++;
}
dbg("TreeRouting", "%s OK, new entry\n", __FUNCTION__);
routingTable[idx].neighbor = from;
routingTable[idx].info.parent = parent;
routingTable[idx].info.etx = etx;
- routingTable[idx].info.haveHeard = 1;
+ routingTable[idx].info.haveHeard = 1;
}
dbg("TreeRouting", "%s OK, updated entry\n", __FUNCTION__);
}