00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00025 #include <cassert>
00026
00027 #include <TransportAddress.h>
00028 #include <NodeHandle.h>
00029 #include <PeerInfo.h>
00030 #include <GlobalStatisticsAccess.h>
00031 #include <CoordMessages_m.h>
00032 #include <GlobalNodeListAccess.h>
00033 #include <hashWatch.h>
00034
00035 #include "NeighborCache.h"
00036
00037
00038 const std::vector<double> NeighborCache::coordsDummy;
00039
00040 std::ostream& operator<<(std::ostream& os,
00041 const NeighborCache::NeighborCacheEntry& entry)
00042 {
00043 if (entry.rttState == NeighborCache::RTTSTATE_VALID) {
00044 os << entry.rtt;
00045 } else {
00046 if (entry.rttState == NeighborCache::RTTSTATE_TIMEOUT) os << "TIMEOUT";
00047 else if (entry.rttState == NeighborCache::RTTSTATE_UNKNOWN) os << "UNKNOWN";
00048 else if (entry.rttState == NeighborCache::RTTSTATE_WAITING) os << "WAITING";
00049 }
00050 os << " (inserted: " << entry.insertTime;
00051
00052 os << ", #contexts: "
00053 << entry.waitingContexts.size();
00054
00055 if (!entry.nodeRef.isUnspecified()) os << ", <KEY>";
00056
00057
00058
00059 os << ")";
00060
00061 return os;
00062 }
00063
00064
00065 Define_Module(NeighborCache);
00066
00067 void NeighborCache::initializeApp(int stage)
00068 {
00069 if (stage != MAX_STAGE_COMPONENTS) {
00070 return;
00071 }
00072
00073 neighborCache.clear();
00074 WATCH_UNORDERED_MAP(neighborCache);
00075
00076 enableNeighborCache = par("enableNeighborCache");
00077 rttExpirationTime = par("rttExpirationTime");
00078 maxSize = par("maxSize");
00079 doDiscovery =par("doDiscovery");
00080
00081
00082 std::string temp = par("defaultQueryType").stdstringValue();
00083 if (temp == "exact")
00084 defaultQueryType = NEIGHBORCACHE_EXACT;
00085 else if (temp == "exact_timeout")
00086 defaultQueryType = NEIGHBORCACHE_EXACT_TIMEOUT;
00087 else if (temp == "available")
00088 defaultQueryType = NEIGHBORCACHE_AVAILABLE;
00089 else if (temp == "estimated")
00090 defaultQueryType = NEIGHBORCACHE_ESTIMATED;
00091 else throw cRuntimeError((std::string("Wrong query type: ")
00092 + temp).c_str());
00093
00094 temp = par("defaultQueryTypeI").stdstringValue();
00095 if (temp == "available")
00096 defaultQueryTypeI = NEIGHBORCACHE_AVAILABLE;
00097 else if (temp == "estimated")
00098 defaultQueryTypeI = NEIGHBORCACHE_ESTIMATED;
00099 else throw cRuntimeError((std::string("Wrong query type (I): ")
00100 + temp).c_str());
00101
00102 temp = par("defaultQueryTypeQ").stdstringValue();
00103 if (temp == "exact")
00104 defaultQueryTypeQ = NEIGHBORCACHE_EXACT;
00105 else if (temp == "exact_timeout")
00106 defaultQueryTypeQ = NEIGHBORCACHE_EXACT_TIMEOUT;
00107 else if (temp == "query")
00108 defaultQueryTypeQ = NEIGHBORCACHE_QUERY;
00109 else throw cRuntimeError((std::string("Wrong query type (Q): ")
00110 + temp).c_str());
00111
00112 temp = par("ncsType").stdstringValue();
00113 if (temp == "none") ncs = NULL;
00114 else if (temp == "vivaldi") ncs = new Vivaldi();
00115 else if (temp == "svivaldi") ncs = new SVivaldi();
00116 else if (temp == "gnp") ncs = new Nps();
00117 else if (temp == "nps") ncs = new Nps();
00118 else throw cRuntimeError((std::string("Wrong NCS type: ")
00119 + temp).c_str());
00120
00121 if (ncs) ncs->init(this);
00122
00123 globalStatistics = GlobalStatisticsAccess().get();
00124
00125 misses = 0;
00126 hits = 0;
00127
00128 rttHistory = par("rttHistory");
00129 timeoutAccuracyLimit = par("timeoutAccuracyLimit");
00130
00131 numMsg = 0;
00132 absoluteError = 0.0;
00133 relativeError = 0.0;
00134 numRttErrorToHigh = 0;
00135 numRttErrorToLow = 0;
00136 lastAbsoluteErrorPerNode.clear();
00137 WATCH(absoluteError);
00138 WATCH(relativeError);
00139 WATCH(numMsg);
00140 }
00141
00142
00143 void NeighborCache::finishApp()
00144 {
00145 if ((misses + hits) != 0) {
00146 globalStatistics
00147 ->addStdDev("NeighborCache: Ping hit rate",
00148 ((double)hits / (double)(misses + hits)));
00149 }
00150
00151 if (ncs && numMsg > 0) {
00152 globalStatistics->addStdDev("NeighborCache: NCS absolute RTT error",
00153 absoluteError / (double)numMsg);
00154 globalStatistics->addStdDev("NeighborCache: NCS relative RTT error",
00155 relativeError / (double)numMsg);
00156 globalStatistics->addStdDev("NeighborCache: number of messages/s",
00157 numMsg / SIMTIME_DBL(simTime() - creationTime));
00158 globalStatistics->addStdDev("NeighborCache: NCS percentage of RTT errors to high",
00159 (double)numRttErrorToHigh / (double)numMsg);
00160 globalStatistics->addStdDev("NeighborCache: NCS percentage of RTT errors to low",
00161 (double)numRttErrorToLow / (double)numMsg);
00162 }
00163 }
00164
00165
00166 NeighborCache::~NeighborCache()
00167 {
00168 delete ncs;
00169 }
00170
00171 bool NeighborCache::insertNodeContext(const TransportAddress& handle,
00172 cPolymorphic* context,
00173 ProxListener* rpcListener,
00174 int rpcId)
00175 {
00176 if (!enableNeighborCache) return false;
00177 if (neighborCache.count(handle) == 0) {
00178 NeighborCacheEntry& entry = neighborCache[handle];
00179
00180 entry.insertTime = simTime();
00181 entry.rttState = RTTSTATE_WAITING;
00182
00183 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00184 handle));
00185
00186 cleanupCache();
00187
00188 assert(neighborCache.size() == neighborCacheExpireMap.size());
00189 return false;
00190 } else {
00191 NeighborCacheEntry& entry = neighborCache[handle];
00192
00193
00194 if (entry.rttState == RTTSTATE_WAITING) {
00195 WaitingContext temp(rpcListener, context, rpcId);
00196 entry.waitingContexts.push_back(temp);
00197
00198 return true;
00199 } else {
00200 if (entry.waitingContexts.size() > 0) {
00201 throw cRuntimeError("not waiting for response,"
00202 " but additional contexts found!");
00203 }
00204
00205 updateEntry(handle, entry.insertTime);
00206
00207 entry.rttState = RTTSTATE_WAITING;
00208 entry.insertTime = simTime();
00209
00210 return false;
00211 }
00212 }
00213 }
00214
00215
00216 NeighborCache::WaitingContexts NeighborCache::getNodeContexts(const TransportAddress& handle)
00217 {
00218 if (neighborCache.count(handle) == 0)
00219 throw cRuntimeError("NeighborCache error!");
00220 WaitingContexts temp = neighborCache[handle].waitingContexts;
00221 neighborCache[handle].waitingContexts.clear();
00222
00223 return temp;
00224 }
00225
00226
00227 void NeighborCache::setNodeTimeout(const TransportAddress& handle)
00228 {
00229
00230
00231 if (neighborCache.count(handle) == 0) {
00232 NeighborCacheEntry& entry = neighborCache[handle];
00233
00234 entry.insertTime = simTime();
00235 entry.rttState = RTTSTATE_TIMEOUT;
00236
00237 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00238 handle));
00239 cleanupCache();
00240 } else {
00241 NeighborCacheEntry& entry = neighborCache[handle];
00242
00243 updateEntry(handle, entry.insertTime);
00244
00245 entry.insertTime = simTime();
00246 entry.rttState = RTTSTATE_TIMEOUT;
00247
00248 WaitingContexts waitingContexts = getNodeContexts(handle);
00249
00250 for (uint32_t i = 0; i < waitingContexts.size(); ++i) {
00251 assert(waitingContexts[i].proxListener || !waitingContexts[i].proxContext);
00252 if (waitingContexts[i].proxListener) {
00253 waitingContexts[i].proxListener->proxCallback(handle,
00254 waitingContexts[i].id,
00255 waitingContexts[i].proxContext,
00256 Prox::PROX_TIMEOUT);
00257 }
00258 }
00259 }
00260 assert(neighborCache.size() == neighborCacheExpireMap.size());
00261 }
00262
00263
00264 void NeighborCache::updateNode(const NodeHandle& add, simtime_t rtt,
00265 const NodeHandle& srcRoute,
00266 AbstractNcsNodeInfo* ncsInfo)
00267 {
00268 Enter_Method_Silent();
00269
00270 EV << "[NeighborCache::updateNode() @ " << thisNode.getAddress()
00271 << " (" << thisNode.getKey().toString(16) << ")]\n"
00272 << " inserting rtt(" << rtt << ") of node " << add.getAddress()
00273 << endl;
00274
00275 if (rtt <= 0) {
00276 delete ncsInfo;
00277 return;
00278 }
00279
00280 bool deleteInfo = false;
00281
00282
00283 if (neighborCache.count(add) == 0) {
00284 NeighborCacheEntry& entry = neighborCache[add];
00285
00286 entry.insertTime = simTime();
00287 entry.rtt = rtt;
00288 entry.rttState = RTTSTATE_VALID;
00289 entry.nodeRef = add;
00290 entry.coordsInfo = ncsInfo;
00291 entry.lastRtts.push_back(rtt);
00292
00293 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime, add));
00294
00295 cleanupCache();
00296 } else {
00297 updateEntry(add, neighborCache[add].insertTime);
00298
00299 NeighborCacheEntry& entry = neighborCache[add];
00300
00301 entry.insertTime = simTime();
00302 if (entry.rttState != RTTSTATE_VALID || entry.rtt > rtt)
00303 entry.rtt = rtt;
00304 entry.rttState = RTTSTATE_VALID;
00305 entry.nodeRef = add;
00306
00307 entry.lastRtts.push_back(rtt);
00308 if (entry.lastRtts.size() > rttHistory) {
00309 entry.lastRtts.pop_front();
00310 }
00311
00312 if (ncsInfo) {
00313 if (entry.coordsInfo) {
00314 entry.coordsInfo->update(*ncsInfo);
00315 deleteInfo = true;
00316 } else {
00317 entry.coordsInfo = ncsInfo;
00318 }
00319 }
00320
00321 WaitingContexts waitingContexts = getNodeContexts(add);
00322
00323 for (uint32_t i = 0; i < waitingContexts.size(); ++i) {
00324 if (waitingContexts[i].proxListener) {
00325 waitingContexts[i].proxListener
00326 ->proxCallback(add,
00327 waitingContexts[i].id,
00328 waitingContexts[i].proxContext,
00329 Prox(rtt, 1));
00330 }
00331 }
00332 }
00333 assert(neighborCache.size() == neighborCacheExpireMap.size());
00334
00335 calcRttError(add, rtt);
00336
00337 if (ncs) ncs->processCoordinates(rtt, *ncsInfo);
00338
00339
00340 if (deleteInfo) delete ncsInfo;
00341 }
00342 void NeighborCache::updateNcsInfo(const TransportAddress& node,
00343 AbstractNcsNodeInfo* ncsInfo)
00344 {
00345 Enter_Method_Silent();
00346
00347 EV << "[NeighborCache::updateNcsInfo() @ " << thisNode.getAddress()
00348 << " (" << thisNode.getKey().toString(16) << ")]\n"
00349 << " inserting new NcsInfo of node " << node.getAddress()
00350 << endl;
00351
00352 if (neighborCache.count(node) == 0) {
00353 NeighborCacheEntry& entry = neighborCache[node];
00354
00355 entry.insertTime = simTime();
00356 entry.coordsInfo = ncsInfo;
00357
00358 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime, node));
00359
00360 cleanupCache();
00361 } else {
00362 updateEntry(node, neighborCache[node].insertTime);
00363
00364 NeighborCacheEntry& entry = neighborCache[node];
00365
00366 if (ncsInfo) {
00367 if (entry.coordsInfo) {
00368 entry.coordsInfo->update(*ncsInfo);
00369 delete ncsInfo;
00370 } else {
00371 entry.coordsInfo = ncsInfo;
00372 }
00373 }
00374 }
00375 }
00376
00377
00378 NeighborCache::Rtt NeighborCache::getNodeRtt(const TransportAddress &add)
00379 {
00380
00381 if (!enableNeighborCache ||
00382 add.isUnspecified() ||
00383 (neighborCache.count(add) == 0)) {
00384 misses++;
00385 return std::make_pair(0.0, RTTSTATE_UNKNOWN);
00386 }
00387
00388 NeighborCacheEntry &entry = neighborCache[add];
00389
00390 if (entry.rttState == RTTSTATE_WAITING ||
00391 entry.rttState == RTTSTATE_UNKNOWN)
00392 return std::make_pair(entry.rtt, entry.rttState);
00393
00394 if ((simTime() - entry.insertTime) >= rttExpirationTime) {
00395 entry.rttState = RTTSTATE_UNKNOWN;
00396 return std::make_pair(entry.rtt, RTTSTATE_UNKNOWN);
00397 }
00398 hits++;
00399 assert(!(entry.rtt == 0.0 && entry.rttState == RTTSTATE_VALID));
00400 return std::make_pair(entry.rtt, entry.rttState);
00401 }
00402
00403
00404 const NodeHandle& NeighborCache::getNodeHandle(const TransportAddress &add)
00405 {
00406 if (neighborCache.count(add) == 0) {
00407 throw cRuntimeError("NeighborCache.cc: getNodeHandle was asked for "
00408 "a non-existent node reference.");
00409 }
00410 return neighborCache[add].nodeRef;
00411 }
00412
00413
00414 bool NeighborCache::cleanupCache()
00415 {
00416 bool result = false;
00417 uint32_t size = neighborCache.size();
00418
00419 if (size > maxSize) {
00420 neighborCacheExpireMapIterator it;
00421 for (uint32_t i = 0; i < (size - (maxSize / 2)); ++i) {
00422 it = neighborCacheExpireMap.begin();
00423 if ((neighborCache[it->second].rttState == RTTSTATE_WAITING) ||
00424 (neighborCache[it->second].insertTime == simTime())) {
00425 break;
00426 }
00427 neighborCache.erase(it->second);
00428 neighborCacheExpireMap.erase(it);
00429 result = true;
00430 }
00431 }
00432 assert(neighborCache.size() == neighborCacheExpireMap.size());
00433 return result;
00434 }
00435
00436
00437 void NeighborCache::updateEntry(const TransportAddress& address,
00438 simtime_t insertTime)
00439 {
00440 neighborCacheExpireMapIterator it =
00441 neighborCacheExpireMap.lower_bound(insertTime);
00442 while (it->second != address) ++it;
00443 neighborCacheExpireMap.erase(it);
00444 neighborCacheExpireMap.insert(std::make_pair(simTime(),
00445 address));
00446 assert(neighborCache.size() == neighborCacheExpireMap.size());
00447 }
00448
00449
00450 TransportAddress NeighborCache::getNearestNode(uint8_t maxLayer)
00451 {
00452 TransportAddress nearestNode = TransportAddress::UNSPECIFIED_NODE;
00453 simtime_t nearestNodeRtt = MAXTIME;
00454 NeighborCacheIterator it;
00455
00456 for(it = neighborCache.begin(); it != neighborCache.end(); it++ ) {
00457 if (it->second.rtt < nearestNodeRtt &&
00458 it->second.rtt > 0
00459
00460 ) {
00461 nearestNode.setAddress(it->first.getAddress());
00462 nearestNodeRtt = it->second.rtt;
00463 nearestNode.setPort(it->second.nodeRef.getPort());
00464 }
00465 }
00466
00467 return nearestNode;
00468 }
00469
00470
00471 bool NeighborCache::isEntry(const TransportAddress &node)
00472 {
00473 if (neighborCache.count(node) > 0) return true;
00474 return false;
00475 }
00476
00477
00478
00479 double NeighborCache::getAvgAbsPredictionError()
00480 {
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 double absoluteDiff = 0;
00505 uint32_t numNeighbors = 0;
00506 uint32_t sampleSize = 32;
00507
00508 for (std::map<simtime_t, TransportAddress>::reverse_iterator it =
00509 neighborCacheExpireMap.rbegin();
00510 it != neighborCacheExpireMap.rend() &&
00511 numNeighbors < sampleSize; ++it) {
00512 NeighborCacheEntry& cacheEntry = neighborCache[it->second];
00513
00514 double dist = ncs->getOwnNcsInfo().getDistance(*cacheEntry.coordsInfo);
00515
00516 if (dist != 0 && cacheEntry.rttState == RTTSTATE_VALID) {
00517 double predictionError = fabs(dist - SIMTIME_DBL(cacheEntry.rtt));
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 numNeighbors++;
00529 absoluteDiff += predictionError;
00530 }
00531 }
00532 assert(numNeighbors != 0);
00533 absoluteDiff /= numNeighbors;
00534
00535 return (absoluteDiff > 1.0) ? 1.0 : absoluteDiff;
00536 }
00537
00538
00539 void NeighborCache::handleReadyMessage(CompReadyMessage* readyMsg)
00540 {
00541 if (readyMsg->getReady() && readyMsg->getComp() == BOOTSTRAPLIST_COMP) {
00542 if (doDiscovery) {
00543
00544
00545
00546
00547
00548 } else {
00549 sendReadyMessage();
00550 }
00551 }
00552 delete readyMsg;
00553 }
00554
00555
00556 void NeighborCache::handleTimerEvent(cMessage* msg)
00557 {
00558 if (ncs) {
00559 ncs->handleTimerEvent(msg);
00560 }
00561 }
00562
00563
00564 bool NeighborCache::handleRpcCall(BaseCallMessage* msg)
00565 {
00566 if (ncs) {
00567 return ncs->handleRpcCall(msg);
00568 }
00569
00570 return false;
00571 }
00572
00573
00574 Prox NeighborCache::getProx(const TransportAddress &node,
00575 NeighborCacheQueryType type,
00576 int rpcId,
00577 ProxListener *listener,
00578 cPolymorphic *contextPointer)
00579 {
00580 Enter_Method("getProx()");
00581
00582 if (!enableNeighborCache) {
00583 queryProx(node, rpcId, listener, contextPointer);
00584 return Prox::PROX_UNKNOWN;
00585 }
00586
00587 if (node == overlay->getThisNode()) {
00588 delete contextPointer;
00589 return Prox::PROX_SELF;
00590 }
00591
00592 bool sendQuery = false;
00593 Prox result = Prox::PROX_UNKNOWN;
00594 Rtt rtt = getNodeRtt(node);
00595
00596
00597 if (type == NEIGHBORCACHE_DEFAULT) type = defaultQueryType;
00598 else if (type == NEIGHBORCACHE_DEFAULT_IMMEDIATELY) type = defaultQueryTypeI;
00599 else if (type == NEIGHBORCACHE_DEFAULT_QUERY) type = defaultQueryTypeQ;
00600
00601 switch(type) {
00602 case NEIGHBORCACHE_EXACT:
00603 if (rtt.second == RTTSTATE_TIMEOUT) {
00604
00605 sendQuery = true;
00606 } else if (rtt.second == RTTSTATE_WAITING) {
00607
00608 sendQuery = true;
00609 } else if (rtt.second == RTTSTATE_UNKNOWN) {
00610
00611 sendQuery = true;
00612 } else {
00613
00614 result = rtt.first;
00615 }
00616 break;
00617 case NEIGHBORCACHE_EXACT_TIMEOUT:
00618 if (rtt.second == RTTSTATE_TIMEOUT) {
00619
00620 result = Prox::PROX_TIMEOUT;
00621 } else if (rtt.second == RTTSTATE_WAITING) {
00622
00623 sendQuery = true;
00624 } else if (rtt.second == RTTSTATE_UNKNOWN) {
00625
00626 sendQuery = true;
00627 } else {
00628
00629 result = rtt.first;
00630 }
00631 break;
00632 case NEIGHBORCACHE_ESTIMATED:
00633 if (rtt.second == RTTSTATE_TIMEOUT) {
00634
00635 result = Prox::PROX_TIMEOUT;
00636 } else if (rtt.second == RTTSTATE_WAITING) {
00637
00638 result = estimateProx(node);
00639 } else if (rtt.second == RTTSTATE_UNKNOWN) {
00640
00641 result = estimateProx(node);
00642 } else {
00643
00644 result = rtt.first;
00645 }
00646 break;
00647 case NEIGHBORCACHE_AVAILABLE:
00648 if (rtt.second == RTTSTATE_TIMEOUT) {
00649
00650 result = Prox::PROX_TIMEOUT;
00651 } else if ((rtt.second == RTTSTATE_WAITING) ||
00652 (rtt.second == RTTSTATE_UNKNOWN)) {
00653
00654 } else {
00655
00656 result = rtt.first;
00657 }
00658 break;
00659 case NEIGHBORCACHE_QUERY:
00660
00661 sendQuery = true;
00662 break;
00663 default:
00664 throw cRuntimeError("Unknown query type!");
00665 break;
00666
00667 }
00668 if (sendQuery) {
00669 if (!insertNodeContext(node, contextPointer, listener, rpcId)) {
00670 queryProx(node, rpcId, listener, contextPointer);
00671 }
00672 } else delete contextPointer;
00673
00674 return result;
00675 }
00676
00677 Prox NeighborCache::estimateProx(const TransportAddress &node)
00678 {
00679 Enter_Method("estimateProx()");
00680
00681 Rtt rtt = getNodeRtt(node);
00682
00683 if (rtt.second != RTTSTATE_UNKNOWN) return rtt.first;
00684
00685 if (ncs && neighborCache.count(node)) {
00686 return getCoordinateBasedProx(node);
00687 }
00688
00689 return Prox::PROX_UNKNOWN;
00690 }
00691
00692 void NeighborCache::queryProx(const TransportAddress &node,
00693 int rpcId,
00694 ProxListener *listener,
00695 cPolymorphic *contextPointer)
00696 {
00697 Enter_Method("queryProx()");
00698
00699 WaitingContext temp(listener, contextPointer, rpcId);
00700
00701 if (neighborCache.count(node) == 0) {
00702 NeighborCacheEntry& entry = neighborCache[node];
00703
00704 entry.waitingContexts.push_back(temp);
00705 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00706 node));
00707 cleanupCache();
00708 } else {
00709 NeighborCacheEntry& entry = neighborCache[node];
00710 entry.waitingContexts.push_back(temp);
00711 }
00712 assert(neighborCache.size() == neighborCacheExpireMap.size());
00713
00714
00715 pingNode(node, -1, 0, NULL, "PING");
00716 }
00717
00718 Prox NeighborCache::getCoordinateBasedProx(const TransportAddress& node)
00719 {
00720 if (ncs && isEntry(node)) {
00721 const AbstractNcsNodeInfo* temp = getNodeCoordsInfo(node);
00722 if (temp) return ncs->getCoordinateBasedProx(*temp);
00723 }
00724 return Prox::PROX_UNKNOWN;
00725 }
00726
00727
00728 const AbstractNcsNodeInfo* NeighborCache::getNodeCoordsInfo(const TransportAddress &node)
00729 {
00730 if (neighborCache.count(node) == 0) {
00731 throw cRuntimeError("NeighborCache.cc: getNodeCoords was asked for "
00732 "a non-existent node reference.");
00733 }
00734 return neighborCache[node].coordsInfo;
00735 }
00736
00737
00738 void NeighborCache::calcRttError(const NodeHandle& handle, simtime_t rtt)
00739 {
00740 if (!ncs) return;
00741
00742
00743 if (!globalStatistics->isMeasuring()) return;
00744
00745 Prox prox = getCoordinateBasedProx(handle);
00746 if (prox == Prox::PROX_UNKNOWN) return;
00747
00748
00749 double tempRttError = prox.proximity - SIMTIME_DBL(rtt);
00750
00751 if (tempRttError < 0){
00752 tempRttError *= -1;
00753 ++numRttErrorToLow;
00754 } else ++numRttErrorToHigh;
00755
00756 numMsg++;
00757 absoluteError += tempRttError;
00758 relativeError += tempRttError / SIMTIME_DBL(rtt);
00759
00760 globalStatistics->recordOutVector("NCS: absolute Rtt Error",
00761 tempRttError);
00762 globalStatistics->recordOutVector("NCS: relative Rtt Error",
00763 (tempRttError / SIMTIME_DBL(rtt)));
00764 }
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 std::pair<simtime_t, simtime_t> NeighborCache::getMeanVarRtt(const TransportAddress &node,
00810 bool returnVar)
00811 {
00812 if (neighborCache.count(node) == 0) {
00813 throw cRuntimeError("NeighborCache.cc: getMeanVarRtt was asked for"
00814 "a non-existent node reference.");
00815 }
00816
00817 uint16_t size = neighborCache[node].lastRtts.size();
00818 if (size == 0) return std::make_pair(-1.0,-1.0);
00819
00820 simtime_t rttSum = 0;
00821 for (int i = 0; i < size; i++){
00822 rttSum += neighborCache[node].lastRtts[i];
00823 }
00824 simtime_t meanRtt = rttSum / size;
00825 if (!returnVar) {
00826 return std::make_pair(meanRtt, -1.0);
00827 }
00828 if (size == 1) {
00829 return std::make_pair(meanRtt, 0.0);
00830 }
00831
00832 double sum = 0.0;
00833 for (int i = 0; i < size; i++){
00834 simtime_t tempRtt = neighborCache[node].lastRtts.at(i) - meanRtt;
00835 sum += (SIMTIME_DBL(tempRtt) * SIMTIME_DBL(tempRtt));
00836 }
00837
00838
00839 return std::make_pair(meanRtt, (sum / size));
00840 }
00841
00842
00843 simtime_t NeighborCache::getNodeTimeout(const NodeHandle &node)
00844 {
00845 simtime_t timeout = getRttBasedTimeout(node);
00846 if (timeout == -1 && ncs) return getNcsBasedTimeout(node);
00847 return timeout;
00848 }
00849
00850
00851
00852 simtime_t NeighborCache::getRttBasedTimeout(const NodeHandle &node)
00853 {
00854 simtime_t timeout = -1;
00855
00856
00857 if (isEntry(node)) {
00858 std::pair<simtime_t, simtime_t> temp = getMeanVarRtt(node, true);
00859 simtime_t meanRtt = temp.first;
00860 simtime_t varRtt = temp.second;
00861
00862
00863 if (meanRtt == -1) return -1;
00864 if (varRtt > 0) {
00865
00866 timeout = meanRtt + 4 * varRtt;
00867 } else {
00868
00869 timeout = meanRtt * 1.2;
00870 }
00871
00872 timeout *= RTT_TIMEOUT_ADJUSTMENT;
00873
00874 }
00875 return timeout;
00876 }
00877
00878
00879 simtime_t NeighborCache::getNcsBasedTimeout(const NodeHandle &node)
00880 {
00881 double timeout = -1;
00882 Prox prox = Prox::PROX_UNKNOWN;
00883
00884
00885 if (isEntry(node)) {
00886 prox = getProx(node, NEIGHBORCACHE_ESTIMATED);
00887
00888 if (prox != Prox::PROX_UNKNOWN && prox != Prox::PROX_TIMEOUT &&
00889 prox.proximity > 0 && prox.accuracy > timeoutAccuracyLimit) {
00890 timeout = prox.proximity + (6 * (1 - prox.accuracy));
00891 timeout += NCS_TIMEOUT_CONSTANT;
00892 } else return -1;
00893
00894 if ( timeout < 0)
00895 return -1;
00896 }
00897 return timeout;
00898 }
00899