]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/lib/net/4bitle/LinkEstimatorP.nc
get rid of +5 for rounding, change arg name in functions in CtpInfo to match the...
[tinyos-2.x.git] / tos / lib / net / 4bitle / LinkEstimatorP.nc
index 86f5c64dc178cd774aa3462ae53aa8bc0077eb83..d1cb1af8c22fd2b6207d1400f4fe4864b53aae71 100644 (file)
@@ -29,7 +29,7 @@
  @ Created: April 24, 2006
  */
 
-#include "LinkEstimator.h"
+#include "./LinkEstimator.h"
 
 module LinkEstimatorP {
   provides {
@@ -56,31 +56,31 @@ implementation {
 
   // configure the link estimator and some constants
   enum {
-    // If the eetx estimate is below this threshold
+    // If the etx estimate is below this threshold
     // do not evict a link
-    EVICT_EETX_THRESHOLD = 55,
-    // maximum link update rounds before we expire the link
-    MAX_AGE = 6,
+    EVICT_ETX_THRESHOLD = 65,
     // if received sequence number if larger than the last sequence
     // number by this gap, we reinitialize the link
     MAX_PKT_GAP = 10,
-    BEST_EETX = 0,
+    BEST_ETX = 10,
     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_ETX_VALUE = 0xffff,
     // 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,
     // number of beacons to wait before computing a new
     // BLQ (Beacon-driven Link Quality)
     BLQ_PKT_WINDOW = 3,
-    // largest EETX value that we feed into the link quality EWMA
-    // a value of 60 corresponds to having to make six transmissions
+    // largest ETX value that we feed into the link quality EWMA
+    // a value of 70 corresponds to having to make six transmissions
     // to successfully receive one acknowledgement
-    LARGE_EETX_VALUE = 60
+    LARGE_ETX_VALUE = 70
   };
 
   // keep information about links from the neighbors
@@ -108,8 +108,8 @@ implementation {
   // the packet.
   uint8_t addLinkEstHeaderAndFooter(message_t *msg, uint8_t len) {
     uint8_t newlen;
-    linkest_header_t *hdr;
-    linkest_footer_t *footer;
+    linkest_header_t * ONE hdr;
+    linkest_footer_t * ONE footer;
     uint8_t i, j, k;
     uint8_t maxEntries, newPrevSentIdx;
     dbg("LI", "newlen1 = %d\n", len);
@@ -129,13 +129,22 @@ implementation {
     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++;
       }
     }
@@ -159,9 +168,8 @@ implementation {
     ne->rcvcnt = 0;
     ne->failcnt = 0;
     ne->flags = (INIT_ENTRY | VALID_ENTRY);
-    ne->inage = MAX_AGE;
     ne->inquality = 0;
-    ne->eetx = 0;
+    ne->etx = 0;
   }
 
   // find the index to the entry for neighbor ll_addr
@@ -191,12 +199,12 @@ implementation {
 
   // find the index to the worst neighbor if the eetx
   // estimate is greater than the given threshold
-  uint8_t findWorstNeighborIdx(uint8_t thresholdEETX) {
+  uint8_t findWorstNeighborIdx(uint8_t thresholdETX) {
     uint8_t i, worstNeighborIdx;
-    uint16_t worstEETX, thisEETX;
+    uint16_t worstETX, thisETX;
 
     worstNeighborIdx = INVALID_RVAL;
-    worstEETX = 0;
+    worstETX = 0;
     for (i = 0; i < NEIGHBOR_TABLE_SIZE; i++) {
       if (!(NeighborTable[i].flags & VALID_ENTRY)) {
        dbg("LI", "Invalid so continuing\n");
@@ -210,13 +218,13 @@ implementation {
        dbg("LI", "Pinned entry, so continuing\n");
        continue;
       }
-      thisEETX = NeighborTable[i].eetx;
-      if (thisEETX >= worstEETX) {
+      thisETX = NeighborTable[i].etx;
+      if (thisETX >= worstETX) {
        worstNeighborIdx = i;
-       worstEETX = thisEETX;
+       worstETX = thisETX;
       }
     }
-    if (worstEETX >= thresholdEETX) {
+    if (worstETX >= thresholdETX) {
       return worstNeighborIdx;
     } else {
       return INVALID_RVAL;
@@ -261,45 +269,44 @@ implementation {
   }
 
 
-  // update the EETX estimator
+  // update the ETX estimator
   // 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;
+  void updateETX(neighbor_table_entry_t *ne, uint16_t newEst) {
+    ne->etx = (ALPHA * ne->etx + (10 - ALPHA) * newEst)/10;
   }
 
 
-  // update data driven EETX
-  void updateDEETX(neighbor_table_entry_t *ne) {
+  // update data driven ETX
+  void updateDETX(neighbor_table_entry_t *ne) {
     uint16_t estETX;
 
     if (ne->data_success == 0) {
       // if there were no successful packet transmission in the
       // last window, our current estimate is the number of failed
       // transmissions
-      estETX = (ne->data_total - 1)* 10;
+      estETX = ne->data_total * 10;
     } else {
-      estETX = (10 * ne->data_total) / ne->data_success - 10;
+      estETX = (10 * ne->data_total) / ne->data_success;
       ne->data_success = 0;
       ne->data_total = 0;
     }
-    updateEETX(ne, estETX);
+    updateETX(ne, estETX);
   }
 
 
-  // EETX (Extra Expected number of Transmission)
-  // EETX = ETX - 1
-  // computeEETX returns EETX*10
-  uint8_t computeEETX(uint8_t q1) {
+  // ETX (Expected number of Transmission)
+  // computeETX returns ETX*10
+  uint16_t computeETX(uint8_t q1) {
     uint16_t q;
     if (q1 > 0) {
-      q =  2550 / q1 - 10;
-      if (q > 255) {
-       q = INFINITY;
+      q =  2500 / q1;
+      if (q > 250) {
+       q = VERY_LARGE_ETX_VALUE;
       }
       return (uint8_t)q;
     } else {
-      return INFINITY;
+      return VERY_LARGE_ETX_VALUE;
     }
   }
 
@@ -317,33 +324,24 @@ implementation {
       ne = &NeighborTable[i];
       if (ne->ll_addr == n) {
        if (ne->flags & VALID_ENTRY) {
-         if (ne->inage > 0)
-           ne->inage--;
-         
-         if (ne->inage == 0) {
-           ne->flags ^= VALID_ENTRY;
-           ne->inquality = 0;
+         dbg("LI", "Making link: %d mature\n", i);
+         ne->flags |= MATURE_ENTRY;
+         totalPkt = ne->rcvcnt + ne->failcnt;
+         dbg("LI", "MinPkt: %d, totalPkt: %d\n", minPkt, totalPkt);
+         if (totalPkt < minPkt) {
+           totalPkt = minPkt;
+         }
+         if (totalPkt == 0) {
+           ne->inquality = (ALPHA * ne->inquality) / 10;
          } else {
-           dbg("LI", "Making link: %d mature\n", i);
-           ne->flags |= MATURE_ENTRY;
-           totalPkt = ne->rcvcnt + ne->failcnt;
-           dbg("LI", "MinPkt: %d, totalPkt: %d\n", minPkt, totalPkt);
-           if (totalPkt < minPkt) {
-             totalPkt = minPkt;
-           }
-           if (totalPkt == 0) {
-             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;
-           }
-           ne->rcvcnt = 0;
-           ne->failcnt = 0;
+           newEst = (250UL * 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;
          }
-         updateEETX(ne, computeEETX(ne->inquality));
-       }
-       else {
+         ne->rcvcnt = 0;
+         ne->failcnt = 0;
+         updateETX(ne, computeETX(ne->inquality));
+       } else {
          dbg("LI", " - entry %i is invalid.\n", (int)i);
        }
       }
@@ -368,20 +366,23 @@ implementation {
        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) {
+    // The or with packetGap >= BLQ_PKT_WINDOW is needed in case
+    // failcnt gets reset above
+
+    if (((NeighborTable[idx].rcvcnt + NeighborTable[idx].failcnt) >= BLQ_PKT_WINDOW)
+       || (packetGap >= BLQ_PKT_WINDOW)) {
       updateNeighborTableEst(NeighborTable[idx].ll_addr);
     }
 
+    if (packetGap > MAX_PKT_GAP) {
+      initNeighborIdx(idx, NeighborTable[idx].ll_addr);
+      NeighborTable[idx].lastseq = seq;
+      NeighborTable[idx].rcvcnt = 1;
+    }
   }
 
 
@@ -393,9 +394,9 @@ implementation {
     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));
+       dbg("LI,LITest", "%d:%d inQ=%d, rcv=%d, fail=%d, Q=%d\n",
+           i, ne->ll_addr, ne->inquality, 
+           ne->rcvcnt, ne->failcnt, computeETX(ne->inquality));
       }
     }
   }
@@ -437,14 +438,18 @@ implementation {
   }
 
   // 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_ETX_VALUE;
     } else {
-      return NeighborTable[idx].eetx;
-    };
+      if (NeighborTable[idx].flags & MATURE_ENTRY) {
+       return NeighborTable[idx].etx;
+      } else {
+       return VERY_LARGE_ETX_VALUE;
+      }
+    }
   }
 
   // insert the neighbor at any cost (if there is a room for it)
@@ -464,7 +469,7 @@ implementation {
       initNeighborIdx(nidx, neighbor);
       return SUCCESS;
     } else {
-      nidx = findWorstNeighborIdx(BEST_EETX);
+      nidx = findWorstNeighborIdx(BEST_ETX);
       if (nidx != INVALID_RVAL) {
        dbg("LI", "insert: inserted by replacing an entry for neighbor: %d\n",
            NeighborTable[nidx].ll_addr);
@@ -509,7 +514,7 @@ implementation {
     ne->data_success++;
     ne->data_total++;
     if (ne->data_total >= DLQ_PKT_WINDOW) {
-      updateDEETX(ne);
+      updateDETX(ne);
     }
     return SUCCESS;
   }
@@ -526,7 +531,7 @@ implementation {
     ne = &NeighborTable[nidx];
     ne->data_total++;
     if (ne->data_total >= DLQ_PKT_WINDOW) {
-      updateDEETX(ne);
+      updateDETX(ne);
     }
     return SUCCESS;
   }
@@ -559,7 +564,7 @@ implementation {
   // 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);
+    signal Send.sendDone(msg, error);
   }
 
   // cascade the calls down
@@ -578,7 +583,7 @@ implementation {
   // 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;
 
@@ -621,7 +626,7 @@ implementation {
          initNeighborIdx(nidx, ll_addr);
          updateNeighborEntryIdx(nidx, hdr->seq);
        } else {
-         nidx = findWorstNeighborIdx(EVICT_EETX_THRESHOLD);
+         nidx = findWorstNeighborIdx(EVICT_ETX_THRESHOLD);
          if (nidx != INVALID_RVAL) {
            dbg("LI", "Evicted neighbor %d at idx %d\n",
                NeighborTable[nidx].ll_addr, nidx);
@@ -629,14 +634,20 @@ implementation {
            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);
+
+           /* if the white bit is set, lets ask the router if the path through
+              this link is better than at least one known path - if so
+              lets insert this link into the table.
+           */
+           if (call LinkPacketMetadata.highChannelQuality(msg)) {
+             if (signal CompareBit.shouldInsert(msg, 
+                                                call Packet.getPayload(msg, call Packet.payloadLength(msg)),
+                                                call Packet.payloadLength(msg))) {
+               nidx = findRandomNeighborIdx();
+               if (nidx != INVALID_RVAL) {
+                 signal LinkEstimator.evicted(NeighborTable[nidx].ll_addr);
+                 initNeighborIdx(nidx, ll_addr);
+               }
              }
            }
          }
@@ -690,9 +701,7 @@ implementation {
 
   // application payload pointer is just past the link estimation header
   command void* Packet.getPayload(message_t* msg, uint8_t len) {
-    linkest_header_t *hdr = getHeader(msg);
-    uint8_t footerLen = (hdr->flags & NUM_ENTRIES_FLAG) * sizeof(linkest_header_t);
-    void* payload = call SubPacket.getPayload(msg, len + footerLen);
+    void* payload = call SubPacket.getPayload(msg, len + sizeof(linkest_header_t));
     if (payload != NULL) {
       payload += sizeof(linkest_header_t);
     }