interface LinkEstimator;
interface Init;
interface Packet;
+ interface CompareBit;
}
uses {
interface AMPacket as SubAMPacket;
interface Packet as SubPacket;
interface Receive as SubReceive;
+ interface LinkPacketMetadata;
+ interface Random;
}
}
BEST_EETX = 0,
INVALID_RVAL = 0xff,
INVALID_NEIGHBOR_ADDR = 0xff,
- INFINITY = 0xff,
+ // if we don't know the link quality, we need to return a value so
+ // large that it will not be used to form paths
+ VERY_LARGE_EETX_VALUE = 0xff,
// decay the link estimate using this alpha
// we use a denominator of 10, so this corresponds to 0.2
- ALPHA = 2,
+ ALPHA = 9,
// number of packets to wait before computing a new
// DLQ (Data-driven Link Quality)
DLQ_PKT_WINDOW = 5,
// get the link estimation header in the packet
linkest_header_t* getHeader(message_t* m) {
- return (linkest_header_t*)call SubPacket.getPayload(m, NULL);
+ return (linkest_header_t*)call SubPacket.getPayload(m, sizeof(linkest_header_t));
}
// get the link estimation footer (neighbor entries) in the packet
- linkest_footer_t* getFooter(message_t* m, uint8_t len) {
- return (linkest_footer_t*)(len + (uint8_t *)call Packet.getPayload(m,NULL));
+ linkest_footer_t* getFooter(message_t* ONE m, uint8_t len) {
+ // To get a footer at offset "len", the payload must be len + sizeof large.
+ return (linkest_footer_t* ONE)(len + (uint8_t *)call Packet.getPayload(m,len + sizeof(linkest_footer_t)));
}
// add the link estimation header (seq no) and link estimation
// footer (neighbor entries) in the packet. Call just before sending
// the packet.
- uint8_t addLinkEstHeaderAndFooter(message_t *msg, uint8_t len) {
+ uint8_t addLinkEstHeaderAndFooter(message_t * ONE msg, uint8_t len) {
uint8_t newlen;
linkest_header_t *hdr;
linkest_footer_t *footer;
j = 0;
newPrevSentIdx = 0;
for (i = 0; i < NEIGHBOR_TABLE_SIZE && j < maxEntries; i++) {
+ uint8_t neighborCount;
+ neighbor_stat_entry_t * COUNT(neighborCount) neighborLists;
+ if(maxEntries <= NEIGHBOR_TABLE_SIZE)
+ neighborCount = maxEntries;
+ else
+ neighborCount = NEIGHBOR_TABLE_SIZE;
+
+ neighborLists = TCAST(neighbor_stat_entry_t * COUNT(neighborCount), footer->neighborList);
+
k = (prevSentIdx + i + 1) % NEIGHBOR_TABLE_SIZE;
- if (NeighborTable[k].flags & VALID_ENTRY) {
- footer->neighborList[j].ll_addr = NeighborTable[k].ll_addr;
- footer->neighborList[j].inquality = NeighborTable[k].inquality;
+ if ((NeighborTable[k].flags & VALID_ENTRY) &&
+ (NeighborTable[k].flags & MATURE_ENTRY)) {
+ neighborLists[j].ll_addr = NeighborTable[k].ll_addr;
+ neighborLists[j].inquality = NeighborTable[k].inquality;
newPrevSentIdx = k;
- dbg("LI", "Loaded on footer: %d %d %d\n", j, footer->neighborList[j].ll_addr,
- footer->neighborList[j].inquality);
+ dbg("LI", "Loaded on footer: %d %d %d\n", j, neighborLists[j].ll_addr,
+ neighborLists[j].inquality);
j++;
}
}
// called when new beacon estimate is done
// also called when new DEETX estimate is done
void updateEETX(neighbor_table_entry_t *ne, uint16_t newEst) {
- ne->eetx = (ALPHA * ne->eetx + (10 - ALPHA) * newEst)/10;
+ ne->eetx = (ALPHA * ne->eetx + (10 - ALPHA) * newEst + 5)/10;
}
if (ne->data_success == 0) {
// if there were no successful packet transmission in the
- // last window, assign a large EETX estimate
- estETX = LARGE_EETX_VALUE;
+ // last window, our current estimate is the number of failed
+ // transmissions
+ estETX = (ne->data_total - 1)* 10;
} else {
estETX = (10 * ne->data_total) / ne->data_success - 10;
+ ne->data_success = 0;
+ ne->data_total = 0;
}
updateEETX(ne, estETX);
- ne->data_success = 0;
- ne->data_total = 0;
}
if (q1 > 0) {
q = 2550 / q1 - 10;
if (q > 255) {
- q = INFINITY;
+ q = VERY_LARGE_EETX_VALUE;
}
return (uint8_t)q;
} else {
- return INFINITY;
+ return VERY_LARGE_EETX_VALUE;
}
}
ne->inquality = (ALPHA * ne->inquality) / 10;
} else {
newEst = (255 * ne->rcvcnt) / totalPkt;
- dbg("LI,LITest", " %hu: %hhu -> %hhu", ne->ll_addr, ne->inquality, (ALPHA * ne->inquality + (10-ALPHA) * newEst)/10);
- ne->inquality = (ALPHA * ne->inquality + (10-ALPHA) * newEst)/10;
+ dbg("LI,LITest", " %hu: %hhu -> %hhu", ne->ll_addr, ne->inquality, (ALPHA * ne->inquality + (10-ALPHA) * newEst + 5)/10);
+ ne->inquality = (ALPHA * ne->inquality + (10-ALPHA) * newEst + 5)/10;
}
ne->rcvcnt = 0;
ne->failcnt = 0;
}
// return bi-directional link quality to the neighbor
- command uint8_t LinkEstimator.getLinkQuality(am_addr_t neighbor) {
+ command uint16_t LinkEstimator.getLinkQuality(am_addr_t neighbor) {
uint8_t idx;
idx = findIdx(neighbor);
if (idx == INVALID_RVAL) {
- return INFINITY;
+ return VERY_LARGE_EETX_VALUE;
} else {
- return NeighborTable[idx].eetx;
- };
+ if (NeighborTable[idx].flags & MATURE_ENTRY) {
+ return NeighborTable[idx].eetx;
+ } else {
+ return VERY_LARGE_EETX_VALUE;
+ }
+ }
}
// return the quality of the link: neighor->self
- command uint8_t LinkEstimator.getReverseQuality(am_addr_t neighbor) {
+ command uint16_t LinkEstimator.getReverseQuality(am_addr_t neighbor) {
uint8_t idx;
idx = findIdx(neighbor);
if (idx == INVALID_RVAL) {
- return INFINITY;
+ return VERY_LARGE_EETX_VALUE;
} else {
- return computeEETX(NeighborTable[idx].inquality);
- };
+ if (NeighborTable[idx].flags & MATURE_ENTRY) {
+ return computeEETX(NeighborTable[idx].inquality);
+ } else {
+ return VERY_LARGE_EETX_VALUE;
+ }
+ }
}
// return the quality of the link: self->neighbor
- command uint8_t LinkEstimator.getForwardQuality(am_addr_t neighbor) {
+ command uint16_t LinkEstimator.getForwardQuality(am_addr_t neighbor) {
uint8_t idx;
idx = findIdx(neighbor);
if (idx == INVALID_RVAL) {
- return INFINITY;
+ return VERY_LARGE_EETX_VALUE;
} else {
- return computeEETX(NeighborTable[idx].outquality);
- };
+ if (NeighborTable[idx].flags & MATURE_ENTRY) {
+ return computeEETX(NeighborTable[idx].outquality);
+ } else {
+ return VERY_LARGE_EETX_VALUE;
+ }
+ }
}
// insert the neighbor at any cost (if there is a room for it)
return call Packet.maxPayloadLength();
}
- command void* Send.getPayload(message_t* msg) {
- return call Packet.getPayload(msg, NULL);
+ command void* Send.getPayload(message_t* msg, uint8_t len) {
+ return call Packet.getPayload(msg, len);
}
// called when link estimator generator packet or
// packets from upper layer that are wired to pass through
// link estimator is received
- void processReceivedMessage(message_t* msg, void* payload, uint8_t len) {
+ void processReceivedMessage(message_t* ONE msg, void* COUNT_NOK(len) payload, uint8_t len) {
uint8_t nidx;
uint8_t num_entries;
if (call SubAMPacket.destination(msg) == AM_BROADCAST_ADDR) {
linkest_header_t* hdr = getHeader(msg);
- linkest_footer_t* footer;
+ linkest_footer_t* ONE footer;
am_addr_t ll_addr;
ll_addr = call SubAMPacket.source(msg);
}
}
+
+ /* Graphical explanation of how we get to the head of the
+ * footer in the following code
+ * <---------------------- payloadLen ------------------->
+ * -------------------------------------------------------
+ * linkest_header_t | payload | linkest_footer_t* ...|
+ * -------------------------------------------------------
+ * ^ ^ ^
+ * | | |
+ * subpayload | payloadEnd
+ * |
+ * payloadEnd - footersize*num footers
+ */
+
if ((nidx != INVALID_RVAL) && (num_entries > 0)) {
+ uint8_t payloadLen = call SubPacket.payloadLength(msg);
+ void* COUNT_NOK(payloadLen) subPayload = call SubPacket.getPayload(msg, payloadLen);
+ void* payloadEnd = subPayload + payloadLen;
dbg("LI", "Number of footer entries: %d\n", num_entries);
- footer = (linkest_footer_t*) ((uint8_t *)call SubPacket.getPayload(msg, NULL)
- + call SubPacket.payloadLength(msg)
- - num_entries*sizeof(linkest_footer_t));
+
+ footer = TCAST(linkest_footer_t* COUNT(num_entries), (payloadEnd - (num_entries*sizeof(linkest_footer_t))));
{
- uint8_t i, my_ll_addr;
+ uint8_t i;
+ am_addr_t my_ll_addr;
+ neighbor_stat_entry_t * COUNT(num_entries) neighborLists;
my_ll_addr = call SubAMPacket.address();
+ neighborLists = TCAST(neighbor_stat_entry_t * COUNT(num_entries), footer->neighborList);
for (i = 0; i < num_entries; i++) {
- dbg("LI", "%d %d %d\n", i, footer->neighborList[i].ll_addr,
- footer->neighborList[i].inquality);
- if (footer->neighborList[i].ll_addr == my_ll_addr) {
- updateReverseQuality(ll_addr, footer->neighborList[i].inquality);
+ dbg("LI", "%d %d %d\n", i, neighborLists[i].ll_addr,
+ neighborLists[i].inquality);
+ if (neighborLists[i].ll_addr == my_ll_addr) {
+ updateReverseQuality(ll_addr, neighborLists[i].inquality);
}
}
}
dbg("LI", "Received upper packet. Will signal up\n");
processReceivedMessage(msg, payload, len);
return signal Receive.receive(msg,
- call Packet.getPayload(msg, NULL),
+ call Packet.getPayload(msg, call Packet.payloadLength(msg)),
call Packet.payloadLength(msg));
}
- command void* Receive.getPayload(message_t* msg, uint8_t* len) {
- return call Packet.getPayload(msg, len);
- }
-
- command uint8_t Receive.payloadLength(message_t* msg) {
- return call Packet.payloadLength(msg);
- }
-
command void Packet.clear(message_t* msg) {
call SubPacket.clear(msg);
}
}
// application payload pointer is just past the link estimation header
- command void* Packet.getPayload(message_t* msg, uint8_t* len) {
- uint8_t* payload = call SubPacket.getPayload(msg, len);
- linkest_header_t *hdr;
- hdr = getHeader(msg);
- if (len != NULL) {
- *len = *len - sizeof(linkest_header_t) - sizeof(linkest_footer_t)*(NUM_ENTRIES_FLAG & hdr->flags);
+ command void* Packet.getPayload(message_t* msg, uint8_t len) {
+ void* payload = call SubPacket.getPayload(msg, len + sizeof(linkest_header_t));
+ if (payload != NULL) {
+ payload += sizeof(linkest_header_t);
}
- return payload + sizeof(linkest_header_t);
+ return payload;
}
}