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 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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Ethernet is a widely used networking technology that is used for connecting devices in a local area network (LAN). It was first developed by Xerox Corporation in the 1970s and has since become a standard technology used for LANs worldwide. Ethernet uses a bus topology, where all devices share the same communication medium. There are two main types of Ethernet: Classic Ethernet and Switched Ethernet. Classic Ethernet: The Classic Ethernet is the original Ethernet technology that was developed in the 1970s. It is also known as the "thicknet" or "thinnet" Ethernet. The Classic Ethernet uses coaxial cables as the communication medium. In the Classic Ethernet, data is transmitted using baseband signaling. The Classic Ethernet has two main layers: the Physical layer and the MAC sublayer protocol. 1. Classic Ethernet Physical Layer: The Classic Ethernet Physical Layer is responsible for transmitting data over the communication medium. It uses coaxial cables as the communication medium. There are two types of coaxial cables used in Classic Ethernet: Thicknet and Thinnet. a) Thicknet: Thicknet is a thick coaxial cable that is 0.4 inches in diameter. It is also known as 10Base5 because it supports a maximum data rate of 10 Mbps and can transmit data up to a distance of 500 meters. Thicknet uses a transceiver to transmit and receive data. b) Thinnet: Thinnet is a thin coaxial cable that is 0.2 inches in diameter. It is also known as 10Base2 because it supports a maximum data rate of 10 Mbps and can transmit data up to a distance of 185 meters. Thinnet uses a BNC connector to connect devices to the network. 2. Classic Ethernet MAC Sublayer Protocol: The Classic Ethernet MAC (Media Access Control) Sublayer Protocol is responsible for controlling access to the communication medium. It uses the CSMA/CD (Carrier Sense Multiple Access with Collision Detection) protocol to avoid collisions between data frames. a) CSMA/CD with Binary Exponential Backoff: CSMA/CD is a protocol used by Classic Ethernet to avoid collisions between data frames. It works by sensing the communication medium to check if it is free before transmitting data. If the medium is busy, the device waits for a random amount of time before trying again. If a collision occurs, the devices involved in the collision wait for a random amount of time before retransmitting data. The amount of time the device waits before retransmitting data increases exponentially with each collision, which is known as Binary Exponential Backoff. Switched Ethernet: The Switched Ethernet is a newer Ethernet technology that was developed in the 1990s. It uses switches instead of hubs to connect devices to the network. In the Switched Ethernet, data is transmitted using broadband signaling. The Switched Ethernet has two main layers: the Physical Layer and the MAC Sublayer Protocol. 1. Switched Ethernet Physical Layer: The Switched Ethernet Physical Layer is responsible for transmitting data over the communication medium. It uses twisted-pair cables or fiber optic cables as the communication medium. The most common type of twisted-pair cable used in Switched Ethernet is the 100Base-TX, which supports a maximum data rate of 100 Mbps and can transmit data up to a distance of 100 meters. 2. Switched Ethernet MAC Sublayer Protocol: The Switched Ethernet MAC Sublayer Protocol is responsible for controlling access to the communication medium. It uses the same CSMA/CD protocol as Classic Ethernet but is rarely used since collisions are avoided by using switches instead of hubs. Diagram: Here is a diagram showing the differences between Classic Ethernet and Switched Ethernet: ``` Classic Ethernet Switched Ethernet Communication Medium Coaxial cables Twisted-pair or fiber optic cables Data Transmission Baseband signaling Broadband signaling Maximum Data Rate 10 Mbps 100 Mbps or higher Distance Up to 500 meters (Thicknet) Up to 100 meters (100Base-TX) Access Control CSMA/CD with Binary Exponential Backoff CSMA/CD or Switches ``` In conclusion, Ethernet is a widely used networking technology that is used for connecting devices in a local area network (LAN). There are two main types of Ethernet: Classic Ethernet and Switched Ethernet. Classic Ethernet uses coaxial cables as the communication medium and has a maximum data rate of 10 Mbps while Switched Ethernet uses twisted-pair or fiber optic cables and has a maximum data rate of 100 Mbps or higher. Both Classic Ethernet and Switched Ethernet use the CSMA/CD protocol to avoid collisions between data frames.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值