📄 linkestimatorp.nc
字号:
} } } } // we received seq from the neighbor in idx // update the last seen seq, receive and fail count // refresh the age void updateNeighborEntryIdx(uint8_t idx, uint8_t seq) { uint8_t packetGap; if (NeighborTable[idx].flags & INIT_ENTRY) { dbg("LI", "Init entry update\n"); NeighborTable[idx].lastseq = seq; NeighborTable[idx].flags &= ~INIT_ENTRY; } packetGap = seq - NeighborTable[idx].lastseq; dbg("LI", "updateNeighborEntryIdx: prevseq %d, curseq %d, gap %d\n", NeighborTable[idx].lastseq, seq, packetGap); NeighborTable[idx].lastseq = seq; NeighborTable[idx].rcvcnt++; NeighborTable[idx].inage = MAX_AGE; if (packetGap > 0) { NeighborTable[idx].failcnt += packetGap - 1; } if (packetGap > MAX_PKT_GAP) { NeighborTable[idx].failcnt = 0; NeighborTable[idx].rcvcnt = 1; NeighborTable[idx].inquality = 0; } 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, rcv=%d, fail=%d, Q=%d\n", i, ne->ll_addr, ne->inquality, ne->inage, ne->rcvcnt, ne->failcnt, computeEETX(ne->inquality)); } } } // 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; } } } // 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); 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"); if (signal CompareBit.shouldInsert(msg, call Packet.getPayload(msg, call Packet.payloadLength(msg)), call Packet.payloadLength(msg), call LinkPacketMetadata.highChannelQuality(msg))) { nidx = findRandomNeighborIdx(); if (nidx != INVALID_RVAL) { signal LinkEstimator.evicted(NeighborTable[nidx].ll_addr); initNeighborIdx(nidx, ll_addr); } } } } } } } // 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 + -