exponential backoff algorithm「建议收藏」

exponential backoff algorithm「建议收藏」在看NDN的默认转发策略BestRouteStrategy中提到了指数退避算法,回忆了一下,即为:在一个共享信道的情况下,当网络上的节点在发生冲突时,每个节点节点等待一定的时间后重新发送。在二进制指数退避算法中,等待时间随着以二为底的指数增长。如果重试失败,那么下次的等待时间将会是上次的等待时间二倍。如果重试次数大于最大重试次数,那么包将从包队列中去除。

大家好,又见面了,我是你们的朋友全栈君。

在看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 bool
56 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 downstream
64   if (upstream->getId() == currentDownstream)
65     return false;
66 
67   // forwarding would violate scope
68   if (pitEntry->violatesScope(*upstream))
69     return false;
70 
71   if (wantUnused) {
72     // NextHop must not have unexpired OutRecord
73     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_iterator
87 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 void
107 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 downstream
118     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 downstream
147   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 earliest
159   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::NackReason
176 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 void
188 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 downstream
214       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 waiting
228     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 fw
239 } // namespace nfd

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/148775.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 2021了,真的不要再说 Node.js 是一门编程语言了「建议收藏」

    2021了,真的不要再说 Node.js 是一门编程语言了「建议收藏」Node.js全栈基础1.Node.js光速入门1.1Node.js概述Node.js是什么Node.js不是一门编程语言,它是一个执行JavaScript代码的工具。工具是指可以安装在计算机操作系统之上的软件。为什么浏览器和Node.js都可以运行JavaScript因为浏览器和Node.js都内置了JavaScriptV8Engine。它可以将JavaScript代码编译为计算机能够识别的机器码。3.浏览器中运行的JavaScrip

  • docker mysql日志查看_MySQL查看版本

    docker mysql日志查看_MySQL查看版本查询DockerMySQL的版本号1.查找到当前正在运行的容器#dockerps2.进入mysql容器(命令中不带小括号)#dockerexec-it(mysql的名字,或id)bash3.登录mysql,输入账号密码登录(命令中不带小括号)#mysql-u(root)-p(abcd)登录成功以后,会显示该mysql的详细信息,其中包含版本号…

  • 重装系统后oracle数据库还原_重装系统后管家婆数据库恢复

    重装系统后oracle数据库还原_重装系统后管家婆数据库恢复以下http://database.51cto.com/art/201011/233460.htm  1、首先,将原来的ORACLE文件夹改名,原来的路径是D:/oracle。我暂时改成D:/oracle_old。找来ORACLE(我用的是ORACLE9I)安装光盘,将ORACLE安装在原来安装的目录下,这样恢复起来更加方便,主要是注册表的内容不用修改。2、安装完了之后,系统中又

    2022年10月21日
  • aarch64平台交叉编译strace工具

    aarch64平台交叉编译strace工具aarch64平台交叉编译strace工具

    2022年10月16日
  • Protostuff 介绍

    Protostuff 介绍2019独角兽企业重金招聘Python工程师标准>>>…

  • 语音识别/合成开源项目

    语音识别/合成开源项目转自:https://blog.csdn.net/github_19776427/article/details/52530066语音识别项目:http://www.oschina.net/project/tag/203/tts-speech sf.net http://www.codesoso.net/Search?q=%D3%EF%D2%F4%CA%B6%B1%F0&amp;l=chttp:/…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号