?? linkestimatorp.nc
字號:
if (NeighborTable[idx].rcvcnt >= BLQ_PKT_WINDOW) {
updateNeighborTableEst(NeighborTable[idx].ll_addr);
}
}
// print the neighbor table. for debugging.
void print_neighbor_table() {
uint8_t i;
neighbor_table_entry_t *ne;
for (i = 0; i < NEIGHBOR_TABLE_SIZE; i++) {
ne = &NeighborTable[i];
if (ne->flags & VALID_ENTRY) {
dbg("LI,LITest", "%d:%d inQ=%d, inA=%d, outQ=%d, outA=%d, rcv=%d, fail=%d, biQ=%d\n",
i, ne->ll_addr, ne->inquality, ne->inage, ne->outquality, ne->outage,
ne->rcvcnt, ne->failcnt, computeBidirEETX(ne->inquality, ne->outquality));
}
}
}
// print the packet. for debugging.
void print_packet(message_t* msg, uint8_t len) {
uint8_t i;
uint8_t* b;
b = (uint8_t *)msg->data;
for(i=0; i<len; i++)
dbg_clear("LI", "%x ", b[i]);
dbg_clear("LI", "\n");
}
// initialize the neighbor table in the very beginning
void initNeighborTable() {
uint8_t i;
for (i = 0; i < NEIGHBOR_TABLE_SIZE; i++) {
NeighborTable[i].flags = 0;
}
}
command error_t StdControl.start() {
dbg("LI", "Link estimator start\n");
return SUCCESS;
}
command error_t StdControl.stop() {
return SUCCESS;
}
// initialize the link estimator
command error_t Init.init() {
dbg("LI", "Link estimator init\n");
initNeighborTable();
return SUCCESS;
}
// return bi-directional link quality to the neighbor
command uint16_t LinkEstimator.getLinkQuality(am_addr_t neighbor) {
uint8_t idx;
idx = findIdx(neighbor);
if (idx == INVALID_RVAL) {
return VERY_LARGE_EETX_VALUE;
} else {
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 uint16_t LinkEstimator.getReverseQuality(am_addr_t neighbor) {
uint8_t idx;
idx = findIdx(neighbor);
if (idx == INVALID_RVAL) {
return VERY_LARGE_EETX_VALUE;
} else {
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 uint16_t LinkEstimator.getForwardQuality(am_addr_t neighbor) {
uint8_t idx;
idx = findIdx(neighbor);
if (idx == INVALID_RVAL) {
return VERY_LARGE_EETX_VALUE;
} else {
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)
// even if eviction of a perfectly fine neighbor is called for
command error_t LinkEstimator.insertNeighbor(am_addr_t neighbor) {
uint8_t nidx;
nidx = findIdx(neighbor);
if (nidx != INVALID_RVAL) {
dbg("LI", "insert: Found the entry, no need to insert\n");
return SUCCESS;
}
nidx = findEmptyNeighborIdx();
if (nidx != INVALID_RVAL) {
dbg("LI", "insert: inserted into the empty slot\n");
initNeighborIdx(nidx, neighbor);
return SUCCESS;
} else {
nidx = findWorstNeighborIdx(BEST_EETX);
if (nidx != INVALID_RVAL) {
dbg("LI", "insert: inserted by replacing an entry for neighbor: %d\n",
NeighborTable[nidx].ll_addr);
signal LinkEstimator.evicted(NeighborTable[nidx].ll_addr);
initNeighborIdx(nidx, neighbor);
return SUCCESS;
}
}
return FAIL;
}
// pin a neighbor so that it does not get evicted
command error_t LinkEstimator.pinNeighbor(am_addr_t neighbor) {
uint8_t nidx = findIdx(neighbor);
if (nidx == INVALID_RVAL) {
return FAIL;
}
NeighborTable[nidx].flags |= PINNED_ENTRY;
return SUCCESS;
}
// pin a neighbor so that it does not get evicted
command error_t LinkEstimator.unpinNeighbor(am_addr_t neighbor) {
uint8_t nidx = findIdx(neighbor);
if (nidx == INVALID_RVAL) {
return FAIL;
}
NeighborTable[nidx].flags &= ~PINNED_ENTRY;
return SUCCESS;
}
// called when an acknowledgement is received; sign of a successful
// data transmission; to update forward link quality
command error_t LinkEstimator.txAck(am_addr_t neighbor) {
neighbor_table_entry_t *ne;
uint8_t nidx = findIdx(neighbor);
if (nidx == INVALID_RVAL) {
return FAIL;
}
ne = &NeighborTable[nidx];
ne->data_success++;
ne->data_total++;
if (ne->data_total >= DLQ_PKT_WINDOW) {
updateDEETX(ne);
}
return SUCCESS;
}
// called when an acknowledgement is not received; could be due to
// data pkt or acknowledgement loss; to update forward link quality
command error_t LinkEstimator.txNoAck(am_addr_t neighbor) {
neighbor_table_entry_t *ne;
uint8_t nidx = findIdx(neighbor);
if (nidx == INVALID_RVAL) {
return FAIL;
}
ne = &NeighborTable[nidx];
ne->data_total++;
if (ne->data_total >= DLQ_PKT_WINDOW) {
updateDEETX(ne);
}
return SUCCESS;
}
// called when the parent changes; clear state about data-driven link quality
command error_t LinkEstimator.clearDLQ(am_addr_t neighbor) {
neighbor_table_entry_t *ne;
uint8_t nidx = findIdx(neighbor);
if (nidx == INVALID_RVAL) {
return FAIL;
}
ne = &NeighborTable[nidx];
ne->data_total = 0;
ne->data_success = 0;
return SUCCESS;
}
// user of link estimator calls send here
// slap the header and footer before sending the message
command error_t Send.send(am_addr_t addr, message_t* msg, uint8_t len) {
uint8_t newlen;
newlen = addLinkEstHeaderAndFooter(msg, len);
dbg("LITest", "%s packet of length %hhu became %hhu\n", __FUNCTION__, len, newlen);
dbg("LI", "Sending seq: %d\n", linkEstSeq);
print_packet(msg, newlen);
return call AMSend.send(addr, msg, newlen);
}
// done sending the message that originated by
// the user of this component
event void AMSend.sendDone(message_t* msg, error_t error ) {
return signal Send.sendDone(msg, error);
}
// cascade the calls down
command uint8_t Send.cancel(message_t* msg) {
return call AMSend.cancel(msg);
}
command uint8_t Send.maxPayloadLength() {
return call Packet.maxPayloadLength();
}
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* ONE msg, void* COUNT_NOK(len) payload, uint8_t len) {
uint8_t nidx;
uint8_t num_entries;
dbg("LI", "LI receiving packet, buf addr: %x\n", payload);
print_packet(msg, len);
if (call SubAMPacket.destination(msg) == AM_BROADCAST_ADDR) {
linkest_header_t* hdr = getHeader(msg);
linkest_footer_t* ONE footer;
am_addr_t ll_addr;
ll_addr = call SubAMPacket.source(msg);
dbg("LI", "Got seq: %d from link: %d\n", hdr->seq, ll_addr);
num_entries = hdr->flags & NUM_ENTRIES_FLAG;
print_neighbor_table();
// update neighbor table with this information
// find the neighbor
// if found
// update the entry
// else
// find an empty entry
// if found
// initialize the entry
// else
// find a bad neighbor to be evicted
// if found
// evict the neighbor and init the entry
// else
// we can not accommodate this neighbor in the table
nidx = findIdx(ll_addr);
if (nidx != INVALID_RVAL) {
dbg("LI", "Found the entry so updating\n");
updateNeighborEntryIdx(nidx, hdr->seq);
} else {
nidx = findEmptyNeighborIdx();
if (nidx != INVALID_RVAL) {
dbg("LI", "Found an empty entry\n");
initNeighborIdx(nidx, ll_addr);
updateNeighborEntryIdx(nidx, hdr->seq);
} else {
nidx = findWorstNeighborIdx(EVICT_EETX_THRESHOLD);
if (nidx != INVALID_RVAL) {
dbg("LI", "Evicted neighbor %d at idx %d\n",
NeighborTable[nidx].ll_addr, nidx);
signal LinkEstimator.evicted(NeighborTable[nidx].ll_addr);
initNeighborIdx(nidx, ll_addr);
} else {
dbg("LI", "No room in the table\n");
}
}
}
/* 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 = TCAST(linkest_footer_t* COUNT(num_entries), (payloadEnd - (num_entries*sizeof(linkest_footer_t))));
{
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, neighborLists[i].ll_addr,
neighborLists[i].inquality);
if (neighborLists[i].ll_addr == my_ll_addr) {
updateReverseQuality(ll_addr, neighborLists[i].inquality);
}
}
}
}
print_neighbor_table();
}
}
// new messages are received here
// update the neighbor table with the header
// and footer in the message
// then signal the user of this component
event message_t* SubReceive.receive(message_t* msg,
void* payload,
uint8_t len) {
dbg("LI", "Received upper packet. Will signal up\n");
processReceivedMessage(msg, payload, len);
return signal Receive.receive(msg,
call Packet.getPayload(msg, call Packet.payloadLength(msg)),
call Packet.payloadLength(msg));
}
command void Packet.clear(message_t* msg) {
call SubPacket.clear(msg);
}
// subtract the space occupied by the link estimation
// header and footer from the incoming payload size
command uint8_t Packet.payloadLength(message_t* msg) {
linkest_header_t *hdr;
hdr = getHeader(msg);
return call SubPacket.payloadLength(msg)
- sizeof(linkest_header_t)
- sizeof(linkest_footer_t)*(NUM_ENTRIES_FLAG & hdr->flags);
}
// account for the space used by header and footer
// while setting the payload length
command void Packet.setPayloadLength(message_t* msg, uint8_t len) {
linkest_header_t *hdr;
hdr = getHeader(msg);
call SubPacket.setPayloadLength(msg,
len
+ sizeof(linkest_header_t)
+ sizeof(linkest_footer_t)*(NUM_ENTRIES_FLAG & hdr->flags));
}
command uint8_t Packet.maxPayloadLength() {
return call SubPacket.maxPayloadLength() - sizeof(linkest_header_t);
}
// application payload pointer is just past the link estimation header
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;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -