exponential backoff algorithm
在看NDN的默认转发策略BestRoute Strategy中提到了指数退避算法,回忆了一下,即为:
在一个共享信道的情况下,当网络上的节点在发生冲突时,每个节点节点等待一定的时间后重新发送。在二进制指数退避算法中,等待时间随着以二为底的指数增长。如果重试失败,那么下次的等待时间将会是上次的等待时间二倍。如果重试次数大于最大重试次数,那么包将从包队列中去除。
BestRoute Strategy:把Interest发给具有最小cost的下一跳,没收到要重传时选择次小cost的下一跳
This strategy forwards a new Interest to the lowest-cost nexthop (except downstream). After that, if consumer retransmits the Interest (and is not suppressed according to exponential backoff algorithm), the strategy forwards the Interest again to the lowest-cost nexthop (except downstream) that is not previously used. If all nexthops have been used, the strategy starts over with the first nexthop.
This strategy returns Nack to all downstreams with reason NoRoute if there is no usable nexthop, which may be caused by: (a) the FIB entry contains no nexthop; (b) the FIB nexthop happens to be the sole downstream; (c) the FIB nexthops violate scope.
This strategy returns Nack to all downstreams if all upstreams have returned Nacks. The reason of the sent Nack equals the least severe reason among received Nacks.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */26 #include "best-route-strategy2.hpp"27 #include "core/logger.hpp"28 29 namespace nfd {30 namespace fw {31 32 NFD_LOG_INIT("BestRouteStrategy2");33 34 const Name BestRouteStrategy2::STRATEGY_NAME("ndn:/localhost/nfd/strategy/best-route/%FD%04");35 NFD_REGISTER_STRATEGY(BestRouteStrategy2);36 37 const time::milliseconds BestRouteStrategy2::RETX_SUPPRESSION_INITIAL(10);38 const time::milliseconds BestRouteStrategy2::RETX_SUPPRESSION_MAX(250);39 40 BestRouteStrategy2::BestRouteStrategy2(Forwarder& forwarder, const Name& name)41 : Strategy(forwarder, name)42 , m_retxSuppression(RETX_SUPPRESSION_INITIAL,43 RetxSuppressionExponential::DEFAULT_MULTIPLIER,44 RETX_SUPPRESSION_MAX)45 {46 }47 55 static inline bool56 predicate_NextHop_eligible(const shared_ptr<pit::Entry>& pitEntry,57 const fib::NextHop& nexthop, FaceId currentDownstream,58 bool wantUnused = false,59 time::steady_clock::TimePoint now = time::steady_clock::TimePoint::min())60 {61 shared_ptr<Face> upstream = nexthop.getFace();62 63 // upstream is current downstream64 if (upstream->getId() == currentDownstream)65 return false;66 67 // forwarding would violate scope68 if (pitEntry->violatesScope(*upstream))69 return false;70 71 if (wantUnused) {72 // NextHop must not have unexpired OutRecord73 pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(*upstream);74 if (outRecord != pitEntry->getOutRecords().end() &&75 outRecord->getExpiry() > now) {76 return false;77 }78 }79 80 return true;81 }82 86 static inline fib::NextHopList::const_iterator87 findEligibleNextHopWithEarliestOutRecord(const shared_ptr<pit::Entry>& pitEntry,88 const fib::NextHopList& nexthops,89 FaceId currentDownstream)90 {91 fib::NextHopList::const_iterator found = nexthops.end();92 time::steady_clock::TimePoint earliestRenewed = time::steady_clock::TimePoint::max();93 for (fib::NextHopList::const_iterator it = nexthops.begin(); it != nexthops.end(); ++it) {94 if (!predicate_NextHop_eligible(pitEntry, *it, currentDownstream))95 continue;96 pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(*it->getFace());97 BOOST_ASSERT(outRecord != pitEntry->getOutRecords().end());98 if (outRecord->getLastRenewed() < earliestRenewed) {99 found = it;100 earliestRenewed = outRecord->getLastRenewed();101 }102 }103 return found;104 }105 106 void107 BestRouteStrategy2::afterReceiveInterest(const Face& inFace,108 const Interest& interest,109 shared_ptr<fib::Entry> fibEntry,110 shared_ptr<pit::Entry> pitEntry)111 {112 const fib::NextHopList& nexthops = fibEntry->getNextHops();113 fib::NextHopList::const_iterator it = nexthops.end();114 115 RetxSuppression::Result suppression = m_retxSuppression.decide(inFace, interest, *pitEntry);116 if (suppression == RetxSuppression::NEW) {117 // forward to nexthop with lowest cost except downstream118 it = std::find_if(nexthops.begin(), nexthops.end(),119 bind(&predicate_NextHop_eligible, pitEntry, _1, inFace.getId(),120 false, time::steady_clock::TimePoint::min()));121 122 if (it == nexthops.end()) {123 NFD_LOG_DEBUG(interest << " from=" << inFace.getId() << " noNextHop");124 125 lp::NackHeader nackHeader;126 nackHeader.setReason(lp::NackReason::NO_ROUTE);127 this->sendNack(pitEntry, inFace, nackHeader);128 129 this->rejectPendingInterest(pitEntry);130 return;131 }132 133 shared_ptr<Face> outFace = it->getFace();134 this->sendInterest(pitEntry, outFace);135 NFD_LOG_DEBUG(interest << " from=" << inFace.getId()136 << " newPitEntry-to=" << outFace->getId());137 return;138 }139 140 if (suppression == RetxSuppression::SUPPRESS) {141 NFD_LOG_DEBUG(interest << " from=" << inFace.getId()142 << " suppressed");143 return;144 }145 146 // find an unused upstream with lowest cost except downstream147 it = std::find_if(nexthops.begin(), nexthops.end(),148 bind(&predicate_NextHop_eligible, pitEntry, _1, inFace.getId(),149 true, time::steady_clock::now()));150 if (it != nexthops.end()) {151 shared_ptr<Face> outFace = it->getFace();152 this->sendInterest(pitEntry, outFace);153 NFD_LOG_DEBUG(interest << " from=" << inFace.getId()154 << " retransmit-unused-to=" << outFace->getId());155 return;156 }157 158 // find an eligible upstream that is used earliest159 it = findEligibleNextHopWithEarliestOutRecord(pitEntry, nexthops, inFace.getId());160 if (it == nexthops.end()) {161 NFD_LOG_DEBUG(interest << " from=" << inFace.getId() << " retransmitNoNextHop");162 }163 else {164 shared_ptr<Face> outFace = it->getFace();165 this->sendInterest(pitEntry, outFace);166 NFD_LOG_DEBUG(interest << " from=" << inFace.getId()167 << " retransmit-retry-to=" << outFace->getId());168 }169 }170 175 inline lp::NackReason176 compareLessSevere(lp::NackReason x, lp::NackReason y)177 {178 if (x == lp::NackReason::NONE) {179 return y;180 }181 if (y == lp::NackReason::NONE) {182 return x;183 }184 return static_cast<lp::NackReason>(std::min(static_cast<int>(x), static_cast<int>(y)));185 }186 187 void188 BestRouteStrategy2::afterReceiveNack(const Face& inFace, const lp::Nack& nack,189 shared_ptr<fib::Entry> fibEntry,190 shared_ptr<pit::Entry> pitEntry)191 {192 int nOutRecordsNotNacked = 0;193 Face* lastFaceNotNacked = nullptr;194 lp::NackReason leastSevereReason = lp::NackReason::NONE;195 for (const pit::OutRecord& outR : pitEntry->getOutRecords()) {196 const lp::NackHeader* inNack = outR.getIncomingNack();197 if (inNack == nullptr) {198 ++nOutRecordsNotNacked;199 lastFaceNotNacked = outR.getFace().get();200 continue;201 }202 203 leastSevereReason = compareLessSevere(leastSevereReason, inNack->getReason());204 }205 206 lp::NackHeader outNack;207 outNack.setReason(leastSevereReason);208 209 if (nOutRecordsNotNacked == 1) {210 BOOST_ASSERT(lastFaceNotNacked != nullptr);211 pit::InRecordCollection::const_iterator inR = pitEntry->getInRecord(*lastFaceNotNacked);212 if (inR != pitEntry->getInRecords().end()) {213 // one out-record not Nacked, which is also a downstream214 NFD_LOG_DEBUG(nack.getInterest() << " nack-from=" << inFace.getId() <<215 " nack=" << nack.getReason() <<216 " nack-to(bidirectional)=" << lastFaceNotNacked->getId() <<217 " out-nack=" << outNack.getReason());218 this->sendNack(pitEntry, *lastFaceNotNacked, outNack);219 return;220 }221 }222 223 if (nOutRecordsNotNacked > 0) {224 NFD_LOG_DEBUG(nack.getInterest() << " nack-from=" << inFace.getId() <<225 " nack=" << nack.getReason() <<226 " waiting=" << nOutRecordsNotNacked);227 // continue waiting228 return;229 }230 231 232 NFD_LOG_DEBUG(nack.getInterest() << " nack-from=" << inFace.getId() <<233 " nack=" << nack.getReason() <<234 " nack-to=all out-nack=" << outNack.getReason());235 this->sendNacks(pitEntry, outNack);236 }237 238 } // namespace fw239 } // namespace nfd
exponential backoff algorithm相关推荐
- flume之退避算法backoff algorithm
flume之退避算法backoff algorithm 什么是退避算法: In a single channel contention based medium access control (MAC ...
- 通过Akka学习指数退避(Exponential Backoff)
原文连接:https://mincong.io/cn/exponential-backoff-in-akka/ 前言 在软件开发中,我们免不了要跟各种错误异常打交道.比如说,当一个服务在调用另一个服务 ...
- Binary Exponential Backoff
一.CSMA/CD过程 CSMA/CD就像在没有主持人的座谈会中,所有的参加者都通过一个共同的媒介(空气)来相互 交谈.每个参加者在讲话前,都礼貌地等待别人把话讲完.如果两个客人同时开始讲话,那么他们 ...
- [Android Traffic] 调整定时更新的频率(C2DM与退避算法)
转载自: http://blog.csdn.net/kesenhoo/article/details/7395253 Minimizing the Effect of Regular Updates[ ...
- 小程序 坚屏_如何构建坚如磐石的应用程序
小程序 坚屏 不同的应用程序设计选项概述 (An overview of different app design options) When we design software, we const ...
- 避免大规模故障的微服务架构设计之道
作者:Péter Márton 译者:Jackyrong 本文首先介绍微服务架构存在的风险,然后针对如何避免微服务架构的故障,提出了多种有效的微服务架构中的方法和技术,其中例如服务降级.变更管理.健 ...
- 一文带你复习计网中的重点知识(一万五千字长文)
建议参考西安交通大学计网考后总结及复习资料汇总进行复习 本文是第一次复习时的整理资料,包括缩写名词解释,重要概念,重要算法,各种表以及报文协议 如需pdf,请在下方留言 文章目录 名词解释 填空概念 ...
- CSMACA 与 CSMA/CD 区别
CSMA/CA 载波检测多路存取/碰撞避免(Carrier Sense Multiple Access/Collision Avoidance, CSMA/CA)是802.11无线局域网标准中采用的媒 ...
- AWS DynamoDB的简介与使用
DynamoDB的简介 Amazon Dynamodb是一种快速灵活的NoSQL数据库服务,适用于所有需要一致的单位毫秒延迟的应用程序.它是一个完全管理的云数据库,支持文档和关键价值存储模型.其灵活的 ...
最新文章
- 找啊找啊找木偶,图灵奖得主G. Hinton第一篇论文曝光!
- 需求分析--12章 过程建模
- 三层交换机如何封装trunk_锐捷交换机常用配置命令汇总
- Android Activity动画属性简介
- Winform开发之ADO.NET对象Connection、Command、DataReader、DataAdapter、DataSet和DataTable简介...
- LeetCode 2087. 网格图中机器人回家的最小代价(脑筋急转弯)
- LeetCode 1094. 拼车
- 4.4.3 日期与时间计算
- JAVASCRIPT视频教程推荐==李炎恢JavaScript教程 第一季
- 快速打造 Android 自定义表情库
- 【Android自动化测试】Robot Framework+adb框架(四)——L2层关键字
- html怎么安装系统,一键重装系统_MBR分区一键安装系统教程-爱纯净
- 站内信功能 java_站内信功能
- Android10.0CarAudioZone(一)
- 复变函数(1)-复数及其几何属性
- jeecg官网(jeecg官网 ios开发)
- 【计算机网络学习笔记】分组交换的原理
- 学习笔记:MAC协议 5GNR
- 【七里香】雨下整夜 我的爱溢出就像雨水
- 2018金华高一计算机考试题目,2018年9月金华十校信息技术考试试题(含解析).docx...
热门文章
- 网络写作一年稿酬最高可达150万元
- UVa OJ 126 - The Errant Physicist (粗心的物理学家)
- 手机剪辑视频指南:去水印、加字幕、做转场,统统一键就搞定
- springBoot启动类报错
- 判断抽样检验产品是否合格的步骤
- Could not extract response: no suitable HttpMessageConverter found for response type [class com.exam
- Android真机连接局域网PC服务器的方法
- gamma correct blurring
- 云渲染和渲染农场有什么区别?看完你就明白了
- idea translation翻译插件报-TKK错误