Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a0f0f31d0 | ||
|
|
3b018d4821 | ||
|
|
e313aa1393 | ||
|
|
332f1ff3a9 | ||
|
|
ce39ab528b | ||
|
|
7cbb3e8cfc | ||
|
|
1373e3b231 | ||
|
|
a1e5672497 | ||
|
|
5a012d80f0 | ||
|
|
0f83e159bb | ||
|
|
4375b287dc | ||
|
|
c763b524e6 | ||
|
|
5a5c903134 | ||
|
|
07425fb0db | ||
|
|
1269cbd6a6 | ||
|
|
2923dabc45 |
No files matched your search
Vendored
-76
@@ -1,76 +0,0 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"csignal": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"any": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"hash_map": "cpp",
|
||||
"strstream": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"chrono": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"complex": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"set": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"regex": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"fstream": "cpp",
|
||||
"future": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"cfenv": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"valarray": "cpp",
|
||||
"variant": "cpp",
|
||||
"*.ipp": "cpp"
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
Waf: Entering directory `/home/dutacm/mircc/mircc/ns-3/build'
|
||||
[2694/3114] Compiling src/ndnSIM/examples/ndn-congestion-topo-plugin.cpp
|
||||
[3073/3114] Linking build/src/ndnSIM/examples/ns3-dev-ndn-congestion-topo-plugin-debug
|
||||
Waf: Leaving directory `/home/dutacm/mircc/mircc/ns-3/build'
|
||||
Build commands will be stored in build/compile_commands.json
|
||||
'build' finished successfully (6.154s)
|
||||
Start App
|
||||
test
|
||||
Start App
|
||||
test
|
||||
aa
|
||||
@@ -1,41 +0,0 @@
|
||||
+1.031003200s 5 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData matching=/dst2/%FE%01
|
||||
+1.031003200s 5 ndn-cxx.nfd.Forwarder:onOutgoingData(): [DEBUG] onOutgoingData out=(257,0) data=/dst2/%FE%01
|
||||
+1.031003200s 5 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData finish
|
||||
+1.031003200s 5 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize interest=/dst2/%FE%01 satisfied
|
||||
+1.031003200s 5 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize finish
|
||||
+1.041400800s 3 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData in=(258,0) data=/dst1/%FE%01
|
||||
+1.041400800s 3 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData if1
|
||||
+1.041400800s 3 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData matching=/dst1/%FE%01
|
||||
+1.041400800s 3 ndn-cxx.nfd.Forwarder:onOutgoingData(): [DEBUG] onOutgoingData out=(257,0) data=/dst1/%FE%01
|
||||
+1.041400800s 3 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData finish
|
||||
+1.041400800s 3 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize interest=/dst1/%FE%01 satisfied
|
||||
+1.041400800s 3 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize finish
|
||||
+1.041856800s 3 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData in=(259,0) data=/dst2/%FE%01
|
||||
+1.041856800s 3 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData if1
|
||||
+1.041856800s 3 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData matching=/dst2/%FE%01
|
||||
+1.041856800s 3 ndn-cxx.nfd.Forwarder:onOutgoingData(): [DEBUG] onOutgoingData out=(257,0) data=/dst2/%FE%01
|
||||
+1.041856800s 3 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData finish
|
||||
+1.041856800s 3 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize interest=/dst2/%FE%01 satisfied
|
||||
+1.041856800s 3 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize finish
|
||||
+1.059936800s 2 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData in=(259,0) data=/dst1/%FE%01
|
||||
+1.059936800s 2 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData if1
|
||||
+1.059936800s 2 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData matching=/dst1/%FE%01
|
||||
+1.059936800s 2 ndn-cxx.nfd.Forwarder:onOutgoingData(): [DEBUG] onOutgoingData out=(257,0) data=/dst1/%FE%01
|
||||
+1.059936800s 2 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData finish
|
||||
+1.059936800s 2 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize interest=/dst1/%FE%01 satisfied
|
||||
+1.059936800s 2 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize finish
|
||||
+1.068472800s 2 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData in=(259,0) data=/dst2/%FE%01
|
||||
+1.068472800s 2 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData if1
|
||||
+1.068472800s 2 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData matching=/dst2/%FE%01
|
||||
+1.068472800s 2 ndn-cxx.nfd.Forwarder:onOutgoingData(): [DEBUG] onOutgoingData out=(258,0) data=/dst2/%FE%01
|
||||
+1.068472800s 2 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData finish
|
||||
+1.068472800s 2 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize interest=/dst2/%FE%01 satisfied
|
||||
+1.068472800s 2 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize finish
|
||||
+1.070790400s 0 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData in=(257,0) data=/dst1/%FE%01
|
||||
+1.070790400s 0 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData if1
|
||||
+1.070790400s 0 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData matching=/dst1/%FE%01
|
||||
+1.070790400s 0 ndn-cxx.nfd.Forwarder:onOutgoingData(): [DEBUG] onOutgoingData out=(258,0) data=/dst1/%FE%01
|
||||
+1.070790400s 0 ndn-cxx.nfd.Forwarder:onIncomingData(): [DEBUG] onIncomingData finish
|
||||
+1.070790400s 0 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize interest=/dst1/%FE%01 satisfied
|
||||
+1.070790400s 0 ndn-cxx.nfd.Forwarder:onInterestFinalize(): [DEBUG] onInterestFinalize finish
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <ndn-cxx/lp/pit-token.hpp>
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
#include "common/global.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@@ -51,6 +52,30 @@ GenericLinkService::GenericLinkService(const GenericLinkService::Options& option
|
||||
m_reassembler.beforeTimeout.connect([this] (auto...) { ++this->nReassemblyTimeouts; });
|
||||
m_reliability.onDroppedInterest.connect([this] (const auto& i) { this->notifyDroppedInterest(i); });
|
||||
nReassembling.observe(&m_reassembler);
|
||||
this->nwfq.setC(options.C);
|
||||
// 启动令牌生成流程
|
||||
this->nwfq.startTokenBucket();
|
||||
|
||||
this->sendPacketCallback = [this](){
|
||||
auto vq = this->nwfq.wfqSchedule();
|
||||
while (vq != nullptr) {
|
||||
auto task = vq->front();
|
||||
ssize_t sendQueueLength = getTransport()->getSendQueueLength();
|
||||
ssize_t sendQueueCapacity = getTransport()->getSendQueueCapacity();
|
||||
if (sendQueueLength + 1024 > sendQueueCapacity) {
|
||||
break;
|
||||
}
|
||||
vq->pop();
|
||||
lp::Packet lpPacket(task.interestPtr->wireEncode());
|
||||
|
||||
encodeLpFields(*task.interestPtr, lpPacket);
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket), task.endpointId, true);
|
||||
vq = this->nwfq.wfqSchedule();
|
||||
}
|
||||
getScheduler().schedule(time::nanoseconds(1000 * 1000), this->sendPacketCallback);
|
||||
};
|
||||
getScheduler().schedule(time::nanoseconds(1000 * 1000), this->sendPacketCallback);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -95,11 +120,28 @@ GenericLinkService::sendLpPacket(lp::Packet&& pkt, const EndpointId& endpointId)
|
||||
void
|
||||
GenericLinkService::doSendInterest(const Interest& interest, const EndpointId& endpointId)
|
||||
{
|
||||
lp::Packet lpPacket(interest.wireEncode());
|
||||
if (interest.getName().getPrefix(1).toUri() == "/localhost") {
|
||||
lp::Packet lpPacket(interest.wireEncode());
|
||||
encodeLpFields(interest, lpPacket);
|
||||
this->sendNetPacket(std::move(lpPacket), endpointId, true);
|
||||
} else {
|
||||
auto success = this->nwfq.appendInterest(interest, endpointId);
|
||||
//if (!success) {
|
||||
// // send Nack
|
||||
// lp::Nack nack(interest);
|
||||
// nack.setReason(lp::NackReason::CONGESTION);
|
||||
// if (this->nwfq.canMark(nack)) {
|
||||
// // 拥塞标记
|
||||
// nack.getInterest().setTag(make_shared<lp::CongestionMarkTag>(1));
|
||||
// }
|
||||
// this->receiveNack(nack, endpointId);
|
||||
//}
|
||||
}
|
||||
//lp::Packet lpPacket(interest.wireEncode());
|
||||
|
||||
encodeLpFields(interest, lpPacket);
|
||||
//encodeLpFields(interest, lpPacket);
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket), endpointId, true);
|
||||
//this->sendNetPacket(std::move(lpPacket), endpointId, true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -150,33 +192,20 @@ GenericLinkService::encodeLpFields(const ndn::PacketBase& netPkt, lp::Packet& lp
|
||||
}
|
||||
}
|
||||
|
||||
// add by qjm
|
||||
auto dszTag = netPkt.getTag<lp::DSZTag>();
|
||||
if (dszTag != nullptr) {
|
||||
lpPacket.add<lp::DSZField>(*dszTag);
|
||||
}
|
||||
auto tosTag = netPkt.getTag<lp::TosTag>();
|
||||
if (tosTag != nullptr) {
|
||||
lpPacket.add<lp::TosField>(*tosTag);
|
||||
}
|
||||
|
||||
auto pitToken = netPkt.getTag<lp::PitToken>();
|
||||
if (pitToken != nullptr) {
|
||||
lpPacket.add<lp::PitTokenField>(*pitToken);
|
||||
}
|
||||
|
||||
auto PTag = netPkt.getTag<lp::PTag>();
|
||||
if (PTag != nullptr) {
|
||||
lpPacket.add<lp::PTagField>(*PTag);
|
||||
}
|
||||
|
||||
auto PathidTag = netPkt.getTag<lp::PathidTag>();
|
||||
if (PathidTag != nullptr) {
|
||||
lpPacket.add<lp::PathidTagField>(*PathidTag);
|
||||
}
|
||||
|
||||
auto RpTag = netPkt.getTag<lp::RpTag>();
|
||||
if (RpTag != nullptr) {
|
||||
lpPacket.add<lp::RpTagField>(*RpTag);
|
||||
}
|
||||
|
||||
auto RsTag = netPkt.getTag<lp::RsTag>();
|
||||
if (RsTag != nullptr) {
|
||||
lpPacket.add<lp::RsTagField>(*RsTag);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
shared_ptr<lp::HopCountTag> hopCountTag = netPkt.getTag<lp::HopCountTag>();
|
||||
if (hopCountTag != nullptr) {
|
||||
@@ -386,23 +415,6 @@ GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstP
|
||||
if (firstPkt.has<lp::HopCountTagField>()) {
|
||||
interest->setTag(make_shared<lp::HopCountTag>(firstPkt.get<lp::HopCountTagField>() + 1));
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::PTagField>()) {
|
||||
interest->setTag(make_shared<lp::PTag>(firstPkt.get<lp::PTagField>()));
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::PathidTagField>()) {
|
||||
interest->setTag(make_shared<lp::PathidTag>(firstPkt.get<lp::PathidTagField>()));
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::RpTagField>()) {
|
||||
interest->setTag(make_shared<lp::RpTag>(firstPkt.get<lp::RpTagField>()));
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::RsTagField>()) {
|
||||
interest->setTag(make_shared<lp::RsTag>(firstPkt.get<lp::RsTagField>()));
|
||||
}
|
||||
|
||||
|
||||
if (m_options.enableGeoTags && firstPkt.has<lp::GeoTagField>()) {
|
||||
interest->setTag(make_shared<lp::GeoTag>(firstPkt.get<lp::GeoTagField>()));
|
||||
@@ -451,6 +463,14 @@ GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstP
|
||||
interest->setTag(make_shared<lp::PitToken>(firstPkt.get<lp::PitTokenField>()));
|
||||
}
|
||||
|
||||
// add by qjm
|
||||
if (firstPkt.has<lp::DSZField>()) {
|
||||
interest->setTag(make_shared<lp::DSZTag>(firstPkt.get<lp::DSZField>()));
|
||||
}
|
||||
if (firstPkt.has<lp::TosField>()) {
|
||||
interest->setTag(make_shared<lp::TosTag>(firstPkt.get<lp::TosField>()));
|
||||
}
|
||||
|
||||
this->receiveInterest(*interest, endpointId);
|
||||
}
|
||||
|
||||
@@ -496,7 +516,10 @@ GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt,
|
||||
|
||||
if (firstPkt.has<lp::CongestionMarkField>()) {
|
||||
data->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
|
||||
}
|
||||
}
|
||||
//else if (this->nwfq.canMark(*data)) {
|
||||
// data->setTag(make_shared<lp::CongestionMarkTag>(1));
|
||||
//}
|
||||
|
||||
if (firstPkt.has<lp::NonDiscoveryField>()) {
|
||||
++this->nInNetInvalid;
|
||||
|
||||
@@ -32,10 +32,14 @@
|
||||
#include "lp-reliability.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
#include <ndn-cxx/util/scheduler.hpp>
|
||||
#include "nwfq.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
using namespace ndn::util;
|
||||
|
||||
/** \brief counters provided by GenericLinkService
|
||||
* \note The type name 'GenericLinkServiceCounters' is implementation detail.
|
||||
* Use 'GenericLinkService::Counters' in public API.
|
||||
@@ -158,6 +162,8 @@ public:
|
||||
* To enable, set value of enableGeoTags option to a function that generates `shared_ptr<GeoTag>`
|
||||
*/
|
||||
std::function<std::shared_ptr<ndn::lp::GeoTag>()> enableGeoTags;
|
||||
|
||||
uint64_t C = 10000000;
|
||||
};
|
||||
|
||||
/** \brief counters provided by GenericLinkService
|
||||
@@ -307,6 +313,8 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
time::steady_clock::TimePoint m_nextMarkTime;
|
||||
/// number of marked packets in the current incident of congestion
|
||||
size_t m_nMarkedSinceInMarkingState;
|
||||
NWFQ nwfq;
|
||||
scheduler::EventCallback sendPacketCallback;
|
||||
|
||||
friend class LpReliability;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
//
|
||||
// Created by 阙建明 on 2021/6/14.
|
||||
//
|
||||
|
||||
#include "nwfq.hpp"
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
NFD_LOG_INIT(NWFQ);
|
||||
|
||||
|
||||
uint64_t getTime() {
|
||||
auto time_now = std::chrono::system_clock::now();
|
||||
auto duration_in_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_now.time_since_epoch());
|
||||
return duration_in_ms.count();
|
||||
}
|
||||
|
||||
void VirtualQueue::pop() {
|
||||
if (this->innerQueue.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t dataSize = 8552;
|
||||
auto dszTag = this->innerQueue.front().interestPtr->getTag<lp::DSZTag>();
|
||||
if (dszTag != nullptr) {
|
||||
dataSize = dszTag->get();
|
||||
}
|
||||
this->currentSize -= dataSize;
|
||||
this->innerQueue.pop();
|
||||
}
|
||||
|
||||
bool VirtualQueue::enqueue(const Interest &interest, const EndpointId &endpointId, NWFQ &nwfq) {
|
||||
uint64_t dataSize = 8552;
|
||||
auto dszTag = interest.getTag<lp::DSZTag>();
|
||||
if (dszTag != nullptr) {
|
||||
dataSize = dszTag->get();
|
||||
}
|
||||
// 如果超出HQL 限制,则不入队,可以进行丢弃或者 Nack 处理
|
||||
if (nwfq.totalQueueSize + dataSize >= nwfq.hql) {
|
||||
return false;
|
||||
}
|
||||
// 判断,如果虚拟队列满,则不入队,可以进行丢弃或者Nack处理
|
||||
if (this->currentSize + dataSize >= this->size) {
|
||||
return false;
|
||||
}
|
||||
this->currentSize += dataSize;
|
||||
|
||||
uint64_t seq = this->lastSeq; // 队列为空,则设置序列号为最近一个调度出的包的序列号
|
||||
if (!this->empty()) {
|
||||
seq = this->lastSeq + 1.0 / this->weight * dataSize; // TODO: 此处this->dataSize应该缓存这个流平均Data包大小
|
||||
} else {
|
||||
seq = nwfq.lastSendSeq + 1.0 / this->weight * dataSize;
|
||||
}
|
||||
SendInterestTask sendInterestTask(endpointId, interest, seq);
|
||||
this->lastSeq = seq;
|
||||
// 进入虚拟队列
|
||||
this->innerQueue.emplace(sendInterestTask);
|
||||
nwfq.totalQueueSize += dataSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// bool VirtualQueue::canMark() {
|
||||
// auto currentTime = getTime();
|
||||
// //NFD_LOG_WARN("size: " << this->size << ", current: " << this->currentSize << ", lastSeq: " << this->lastSeq);
|
||||
// if (this->currentSize < this->markThresh) {
|
||||
// this->lastMarkTime = currentTime;
|
||||
// return false;
|
||||
// }
|
||||
// if (currentTime - this->lastMarkTime > this->markInterval) {
|
||||
// // NFD_LOG_INFO("last: " << this->lastMarkTime << ", current: " << currentTime);
|
||||
// this->lastMarkTime = currentTime;
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
bool NWFQ::appendInterest(const Interest &interest, const EndpointId &endpointId) {
|
||||
std::string key = interest.getName().getPrefix(1).toUri();
|
||||
if (this->virtualQueues.count(key) == 0) {
|
||||
this->virtualQueues[key] = std::make_shared<VirtualQueue>(1, this->queueSize);
|
||||
// 当新建一个虚拟队列时,将所有虚拟队列最近发出的序列号作为起始序列号
|
||||
this->virtualQueues[key]->setLastSeq(this->lastSendSeq);
|
||||
|
||||
// 通过提取 Interst 中的Tos Tag设置优先级
|
||||
auto tosTag = interest.getTag<lp::TosTag>();
|
||||
float weight = 1.0;
|
||||
if (tosTag != nullptr) {
|
||||
weight = tosTag->get();
|
||||
}
|
||||
this->virtualQueues[key]->setWeight(weight);
|
||||
return this->virtualQueues[key]->enqueue(interest, endpointId, *this);
|
||||
} else {
|
||||
// 虚拟队列已经存在的情况
|
||||
return this->virtualQueues[key]->enqueue(interest, endpointId, *this);
|
||||
}
|
||||
}
|
||||
|
||||
// bool NWFQ::canMark(const Name &name) {
|
||||
// std::string key = name.getPrefix(1).toUri();
|
||||
// if (this->virtualQueues.count(key) == 0) {
|
||||
// return false;
|
||||
// } else {
|
||||
// return this->virtualQueues[key]->canMark();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// bool NWFQ::canMark(const Data &data) {
|
||||
// return this->canMark(data.getName());
|
||||
// }
|
||||
//
|
||||
// bool NWFQ::canMark(const lp::Nack &nack) {
|
||||
// return this->canMark(nack.getInterest().getName());
|
||||
// }
|
||||
|
||||
std::shared_ptr <VirtualQueue> NWFQ::wfqSchedule() {
|
||||
std::shared_ptr <VirtualQueue> result = nullptr;
|
||||
for (auto &item : this->virtualQueues) {
|
||||
if (!item.second->empty()) {
|
||||
if (result == nullptr || result->frontSeq() > item.second->frontSeq()) {
|
||||
result = item.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64_t dataSize = 8552;
|
||||
auto dszTag = result->front().interestPtr->getTag<lp::DSZTag>();
|
||||
if (dszTag != nullptr) {
|
||||
dataSize = dszTag->get();
|
||||
}
|
||||
|
||||
// 令牌数量不够时,直接返回 nullptr 表示不可调度
|
||||
if (this->tokens < dataSize) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 如果有可调度的队列,且令牌数量足够,则消耗令牌
|
||||
if (result != nullptr) {
|
||||
this->tokens -= dataSize;
|
||||
}
|
||||
|
||||
this->lastSendSeq = result->frontSeq();
|
||||
|
||||
// 通过排队时间判断是否需要标记
|
||||
this->checkCongestionLevel(*result->front().interestPtr);
|
||||
|
||||
this->totalQueueSize -= dataSize;
|
||||
|
||||
auto value = this->tokens;
|
||||
//NFD_LOG_WARN("tokens: " << value << ", " << result->frontSeq() << ", "<< result->front().interestPtr->getName().toUri());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void NWFQ::checkCongestionLevel(const Interest &interest) {
|
||||
if (this->totalQueueSize == 0) {
|
||||
return;
|
||||
}
|
||||
if (this->C == 1000000) {
|
||||
NFD_LOG_DEBUG("TotalQueueSize: " << this->totalQueueSize);
|
||||
}
|
||||
if (this->totalQueueSize > this->markThresh) {
|
||||
NFD_LOG_DEBUG("Fuck");
|
||||
const auto now = time::steady_clock::now();
|
||||
|
||||
if (m_nextMarkTime == time::steady_clock::TimePoint::max()) {
|
||||
m_nextMarkTime = now + this->markInterval;
|
||||
}
|
||||
// Mark packet if sendQueue stays above target for one interval
|
||||
else if (now >= m_nextMarkTime) {
|
||||
interest.setTag(make_shared<lp::CongestionMarkTag>(1));
|
||||
|
||||
++m_nMarkedSinceInMarkingState;
|
||||
// Decrease the marking interval by the inverse of the square root of the number of packets
|
||||
// marked in this incident of congestion
|
||||
time::nanoseconds interval(static_cast<time::nanoseconds::rep>(
|
||||
this->markInterval.count() /
|
||||
std::sqrt(m_nMarkedSinceInMarkingState + 1)));
|
||||
m_nextMarkTime += interval;
|
||||
}
|
||||
} else if (m_nextMarkTime != time::steady_clock::TimePoint::max()) {
|
||||
m_nextMarkTime = time::steady_clock::TimePoint::max();
|
||||
m_nMarkedSinceInMarkingState = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
//
|
||||
// Created by 阙建明 on 2021/6/14.
|
||||
//
|
||||
|
||||
#ifndef TEMPLATE_NWFQ_H
|
||||
#define TEMPLATE_NWFQ_H
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include "link-service.hpp"
|
||||
#include <memory>
|
||||
#include <ndn-cxx/util/scheduler.hpp>
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
#include "common/global.hpp"
|
||||
#include "face-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
using namespace ndn;
|
||||
using namespace ndn::util;
|
||||
|
||||
class NWFQ;
|
||||
|
||||
/**
|
||||
* 兴趣包发送 Task
|
||||
*/
|
||||
struct SendInterestTask {
|
||||
SendInterestTask(const EndpointId &endpointId, const Interest &interest, uint64_t seq) :
|
||||
endpointId(endpointId),
|
||||
interestPtr(interest.shared_from_this()),
|
||||
seq(seq) {
|
||||
}
|
||||
|
||||
EndpointId endpointId;
|
||||
shared_ptr<const Interest> interestPtr;
|
||||
uint64_t seq; // WFQ序列号
|
||||
};
|
||||
|
||||
/**
|
||||
* 虚拟队列实现
|
||||
*/
|
||||
class VirtualQueue {
|
||||
public:
|
||||
explicit VirtualQueue(float weight, uint64_t size) :
|
||||
weight(weight), size(size), currentSize(0){
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 往虚拟队列里面放入一个
|
||||
* @param interest
|
||||
* @param endpointId
|
||||
* @param seq
|
||||
* @param isFirst 是否是创建虚拟队列之后第一次放包
|
||||
* @return
|
||||
*/
|
||||
bool enqueue(const Interest &interest, const EndpointId &endpointId, NWFQ &nwfq);
|
||||
|
||||
/**
|
||||
* 判断虚拟队列是否为空
|
||||
*/
|
||||
bool empty() {
|
||||
return this->innerQueue.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回队头元素的序列号
|
||||
* @return
|
||||
*/
|
||||
uint64_t frontSeq() {
|
||||
if (this->innerQueue.empty()) {
|
||||
return this->lastSeq;
|
||||
}
|
||||
return this->innerQueue.front().seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回虚拟队列队头的元素(调用之前用 empty 判断不为空)
|
||||
* @return
|
||||
*/
|
||||
SendInterestTask front() {
|
||||
return this->innerQueue.front();
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出队头Task
|
||||
*/
|
||||
void pop();
|
||||
|
||||
/**
|
||||
* 设置最近一次分配的序列号
|
||||
* 1. 当这是一个新创建的虚拟队列时,会遍历所有虚拟队列,取所有虚拟队列队头序列号中最小的序列号;
|
||||
* 2. 当这个队列空了一段时间时(超过1秒),会遍历所有虚拟队列,取所有虚拟队列队头序列号中最小的序列号;
|
||||
* @param seq
|
||||
*/
|
||||
void setLastSeq(uint64_t seq) {
|
||||
this->lastSeq = seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最近一次分配的序列号
|
||||
* @return
|
||||
*/
|
||||
uint64_t getLastSeq() {
|
||||
return lastSeq;
|
||||
}
|
||||
|
||||
void setWeight(float weight) {
|
||||
this->weight = weight;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 返回是否可以标记,一个标记周期内,最多可以标记一次
|
||||
// */
|
||||
// bool canMark();
|
||||
|
||||
|
||||
private:
|
||||
float weight; // 队列权重(优先级越高,权重越大)
|
||||
uint64_t size; // 队列大小(单位为字节)
|
||||
int currentSize; // 当前队列占用大小(单位为字节,每个 Task 占用的大小等于其兴趣包对应的数据包的大小)
|
||||
uint64_t lastSeq; // 最近一次分配的序列号
|
||||
uint64_t lastMarkTime; // 最后一次标记的时间
|
||||
std::queue <SendInterestTask> innerQueue; // 存放队列里面的兴趣包发送任务
|
||||
};
|
||||
|
||||
class NWFQ {
|
||||
public:
|
||||
explicit NWFQ() : C(1000000), queueSize(1600000), tokens(0) {
|
||||
this->hql = 200 * 1000 * 8;
|
||||
this->markThresh = 64 * 1000 * 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置带宽大小
|
||||
* @param C
|
||||
*/
|
||||
void setC(uint64_t C) {
|
||||
this->C = C;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置队列的大小
|
||||
* @param queueSize
|
||||
*/
|
||||
void setQueueSize(uint64_t queueSize) {
|
||||
this->queueSize = queueSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个兴趣包
|
||||
* 1. 首先根据兴趣包的名字,取第一个 Component 区分不同的流,放到不同的虚拟队列当中
|
||||
* 2.
|
||||
* @param interest
|
||||
* @param endpointId
|
||||
* @return bool 返回是否入队成功,如果入队失败,则表示对应的虚拟队列已经满了,需要丢弃或者做Nack处理
|
||||
*/
|
||||
bool appendInterest(const Interest &interest, const EndpointId &endpointId);
|
||||
|
||||
// /**
|
||||
// * 判断某个前缀对应的包是否可以标记
|
||||
// */
|
||||
// bool canMark(const Name &name);
|
||||
//
|
||||
// /**
|
||||
// * 判断是否可以给一个Data包标记
|
||||
// */
|
||||
// bool canMark(const Data &data);
|
||||
//
|
||||
// /**
|
||||
// * 判断是否可以给一个 Nack 标记
|
||||
// */
|
||||
// bool canMark(const lp::Nack &nack);
|
||||
|
||||
/**
|
||||
* 返回下一个可调度的虚拟队列
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr <VirtualQueue> wfqSchedule();
|
||||
|
||||
/**
|
||||
* 启动一个定时任务,按链路的带宽作为令牌生成速率,往令牌桶中投放令牌
|
||||
*/
|
||||
void startTokenBucket() {
|
||||
this->generateTokenCallback = [this]() {
|
||||
if (this->tokens + (this->C / 1000) < this->C) {
|
||||
this->tokens += (this->C / 1000);
|
||||
} else {
|
||||
this->tokens = this->C;
|
||||
}
|
||||
getScheduler().schedule(time::nanoseconds(1000 * 1000), this->generateTokenCallback);
|
||||
};
|
||||
getScheduler().schedule(time::nanoseconds(1000 * 1000), this->generateTokenCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否需要对兴趣包进行标记
|
||||
* @param interest
|
||||
*/
|
||||
void checkCongestionLevel(const Interest &interest);
|
||||
|
||||
public:
|
||||
uint64_t hql; // Hold-Queue-Limit
|
||||
uint64_t totalQueueSize = 0; // 所有虚拟队列总的占用率
|
||||
uint64_t lastSendSeq = 1;
|
||||
uint64_t markThresh; // 标记阈值,为队列大小的10%
|
||||
time::nanoseconds markInterval = 100_ms; // 标记周期 => 100 ms
|
||||
time::steady_clock::TimePoint m_nextMarkTime;
|
||||
/// number of marked packets in the current incident of congestion
|
||||
size_t m_nMarkedSinceInMarkingState;
|
||||
|
||||
private:
|
||||
uint64_t C; // 带宽
|
||||
uint64_t queueSize; // 队列大小
|
||||
uint64_t tokens; // 令牌桶中的令牌
|
||||
scheduler::EventCallback generateTokenCallback;
|
||||
std::unordered_map <std::string, std::shared_ptr<VirtualQueue>> virtualQueues; // 虚拟队列
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //TEMPLATE_NWFQ_H
|
||||
|
||||
@@ -277,7 +277,6 @@ Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry)
|
||||
// PIT delete
|
||||
pitEntry->expiryTimer.cancel();
|
||||
m_pit.erase(pitEntry.get());
|
||||
NFD_LOG_DEBUG("onInterestFinalize finish");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -310,7 +309,6 @@ Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
|
||||
|
||||
// when only one PIT entry is matched, trigger strategy: after receive Data
|
||||
if (pitMatches.size() == 1) {
|
||||
NFD_LOG_DEBUG("onIncomingData if1");
|
||||
auto& pitEntry = pitMatches.front();
|
||||
|
||||
NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
|
||||
@@ -336,7 +334,6 @@ Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
|
||||
// when more than one PIT entry is matched, trigger strategy: before satisfy Interest,
|
||||
// and send Data to all matched out faces
|
||||
else {
|
||||
NFD_LOG_DEBUG("onIncomingData if2");
|
||||
std::set<std::pair<Face*, EndpointId>> pendingDownstreams;
|
||||
auto now = time::steady_clock::now();
|
||||
|
||||
@@ -369,6 +366,7 @@ Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
|
||||
pitEntry->clearInRecords();
|
||||
pitEntry->deleteOutRecord(ingress.face);
|
||||
}
|
||||
|
||||
// foreach pending downstream
|
||||
for (const auto& pendingDownstream : pendingDownstreams) {
|
||||
if (pendingDownstream.first->getId() == ingress.face.getId() &&
|
||||
@@ -380,7 +378,6 @@ Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
|
||||
this->onOutgoingData(data, FaceEndpoint(*pendingDownstream.first, pendingDownstream.second));
|
||||
}
|
||||
}
|
||||
NFD_LOG_DEBUG("onIncomingData finish");
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,473 +0,0 @@
|
||||
#include "mircc-strategy.hpp"
|
||||
|
||||
NFD_LOG_INIT(MIRCCStrategy);
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
MIRCCStrategy::MIRCCStrategy(Forwarder &forwarder, const ndn::Name &name)
|
||||
: Strategy(forwarder), ProcessNackTraits<MIRCCStrategy>(this)
|
||||
{
|
||||
this->setInstanceName(makeInstanceName(name, getStrategyName()));
|
||||
const FaceTable &faceTable = getFaceTable();
|
||||
for (auto& tmp : faceTable)
|
||||
{
|
||||
m_Rp_base[tmp.getId()] = getMaxR();
|
||||
m_Rp_ex[tmp.getId()] = 0;
|
||||
m_Rs_base[tmp.getId()] = 0;
|
||||
m_Rs_ex[tmp.getId()] = 0;
|
||||
|
||||
m_Yp[tmp.getId()] = 0;
|
||||
m_Yp_old[tmp.getId()] = 0;
|
||||
m_Ys[tmp.getId()] = 0;
|
||||
m_Ys_old[tmp.getId()] = 0;
|
||||
|
||||
m_d[tmp.getId()] = 500;
|
||||
m_ratio[tmp.getId()] = 3000 / INTEREST_SIZE;
|
||||
m_linkC[tmp.getId()] = 10 * 1000 * 1000 * 8;
|
||||
|
||||
sendQueueInterest(tmp.getId());
|
||||
|
||||
calcRt(tmp.getId());
|
||||
|
||||
}
|
||||
|
||||
//初始化hash
|
||||
hashUnit[0] = 1;
|
||||
for (int i = 1;i < 100;i++)
|
||||
{
|
||||
hashUnit[i] = hashUnit[i - 1] * hashNum % hashMo;
|
||||
}
|
||||
|
||||
//初始化逆元
|
||||
invMod = fpow(hashNum,hashMo - 2,hashMo);
|
||||
}
|
||||
|
||||
const Name&
|
||||
MIRCCStrategy::getStrategyName()
|
||||
{
|
||||
static Name strategyName("/localhost/nfd/strategy/mircc/%FD%01");
|
||||
return strategyName;
|
||||
}
|
||||
|
||||
void
|
||||
MIRCCStrategy::sendQueueInterest(FaceId mface)
|
||||
{
|
||||
|
||||
//设置下一次发送,根据兴趣包与数据包的大小之比,计算出兴趣包可用带宽,进而计算出每发送一个兴趣包需要的时间,最小为1ms
|
||||
//time::nanoseconds ttime((int)std::max((double)1,1000000000 * INTEREST_SIZE / (m_linkC[mface] * (1.0 / (m_ratio[mface] + 1)))));
|
||||
time::nanoseconds ttime(100000000);
|
||||
//NS_LOG_DEBUG(ttime);
|
||||
getScheduler().schedule(ttime, bind(&MIRCCStrategy::sendQueueInterest, this, mface));
|
||||
|
||||
//清空队列中过期的兴趣包
|
||||
//refreshQueueInterest(mface);
|
||||
|
||||
//分三种情况讨论,只有第一类兴趣包可以发,只有第二类兴趣包可以发,两类可以发(选择最早到达的)
|
||||
if (m_Queue[mface].qp.size() > 0 and m_Queue[mface].qs.size() == 0)
|
||||
{
|
||||
//发送兴趣包
|
||||
shared_ptr<Interest> interest = m_Queue[mface].qp.front();
|
||||
sendInterest(m_Queue[mface].pp.front(),FaceEndpoint(*getFaceTable().get(mface),0),*interest);
|
||||
//这个位置是不是要设置pit记录的过期时间?似乎sendInterest里面实现了这个功能
|
||||
m_Queue[mface].qp.pop_front();
|
||||
m_Queue[mface].tp.pop_front();
|
||||
m_Queue[mface].pp.pop_front();
|
||||
NS_LOG_DEBUG("MIRCCStrategy::sendQueueInterest1");
|
||||
|
||||
}else if (m_Queue[mface].qs.size() > 0 and m_Queue[mface].qp.size() == 0)
|
||||
{
|
||||
//发送兴趣包
|
||||
shared_ptr<Interest> interest = m_Queue[mface].qp.front();
|
||||
sendInterest(m_Queue[mface].ps.front(),FaceEndpoint(*getFaceTable().get(mface),0),*interest);
|
||||
//这个位置是不是要设置pit记录的过期时间?似乎sendInterest里面实现了这个功能
|
||||
m_Queue[mface].qs.pop_front();
|
||||
m_Queue[mface].ts.pop_front();
|
||||
m_Queue[mface].ps.pop_front();
|
||||
NS_LOG_DEBUG("MIRCCStrategy::sendQueueInterest2");
|
||||
}else if (m_Queue[mface].qs.size() > 0 and m_Queue[mface].qp.size() > 0)
|
||||
{
|
||||
//如果第一类兴趣包更早到达
|
||||
if (m_Queue[mface].tp.front() < m_Queue[mface].ts.front())
|
||||
{
|
||||
//发送兴趣包
|
||||
shared_ptr<Interest> interest =m_Queue[mface].qp.front();
|
||||
sendInterest(m_Queue[mface].pp.front(),FaceEndpoint(*getFaceTable().get(mface),0),*interest);
|
||||
//这个位置是不是要设置pit记录的过期时间?似乎sendInterest里面实现了这个功能
|
||||
m_Queue[mface].qp.pop_front();
|
||||
m_Queue[mface].tp.pop_front();
|
||||
m_Queue[mface].pp.pop_front();
|
||||
NS_LOG_DEBUG("MIRCCStrategy::sendQueueInterest1 e");
|
||||
}else
|
||||
{
|
||||
//发送兴趣包
|
||||
shared_ptr<Interest> interest = m_Queue[mface].qp.front();
|
||||
sendInterest(m_Queue[mface].ps.front(),FaceEndpoint(*getFaceTable().get(mface),0),*interest);
|
||||
//这个位置是不是要设置pit记录的过期时间?似乎sendInterest里面实现了这个功能
|
||||
m_Queue[mface].qs.pop_front();
|
||||
m_Queue[mface].ts.pop_front();
|
||||
m_Queue[mface].ps.pop_front();
|
||||
NS_LOG_DEBUG("MIRCCStrategy::sendQueueInterest2 e");
|
||||
}
|
||||
}else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MIRCCStrategy::calcRt(FaceId mface)
|
||||
{
|
||||
//每100ms自动重新计算Rt
|
||||
time::nanoseconds ttime(100000000);
|
||||
getScheduler().schedule(ttime, std::bind(&MIRCCStrategy::calcRt, this, mface));
|
||||
|
||||
uint64_t ia,ib,Rp,Rs;
|
||||
Rp = m_Rp_base[mface] + m_Rp_ex[mface];
|
||||
Rs = m_Rs_base[mface] + m_Rs_ex[mface];
|
||||
|
||||
//Rp计算过程
|
||||
ia = std::max(m_linkC[mface],m_Yp[mface]);
|
||||
|
||||
ib = std::max(Rp,(uint64_t)1);
|
||||
uint64_t Np = ia / ib;
|
||||
|
||||
ia = m_Yp[mface] - m_Yp_old[mface];
|
||||
|
||||
ib = std::max(m_Yp[mface],(uint64_t)1);
|
||||
double Bp = std::max(m_B,(double)ia / ib);
|
||||
|
||||
ia = m_miu * m_linkC[mface] - Bp * getQt(mface) / std::max(m_d[mface],(uint64_t)1);
|
||||
|
||||
ib = std::max(Np,(uint64_t)1);
|
||||
m_Rp_base[mface] = m_a * m_Rp_base[mface] + (1 - m_a) * ia / ib;
|
||||
|
||||
ia = m_Yp[mface];
|
||||
|
||||
ib = std::max(Np,(uint64_t)1);
|
||||
m_Rp_ex[mface] = m_a * m_Rp_ex[mface] + (1 - m_a) * (Rp - ia / ib);
|
||||
|
||||
m_Yp_old[mface] = m_Yp[mface];
|
||||
|
||||
//Rs计算过程
|
||||
uint64_t Cs = std::max(m_linkC[mface] - m_Yp[mface],(uint64_t)0);
|
||||
|
||||
uint64_t Ns = std::max(std::max(Cs,m_Ys[mface]) / std::max(Rs,(uint64_t)1) ,(uint64_t)1);
|
||||
|
||||
ia = m_Ys[mface] - m_Ys_old[mface];
|
||||
ib = std::max(m_Ys[mface],(uint64_t)1);
|
||||
double Bs = std::max(m_B,(double)ia / ib);
|
||||
|
||||
ia = m_miu * Cs - Bs * getQt(mface) / std::max(m_d[mface],(uint64_t)1);
|
||||
ib = std::max(Ns,(uint64_t)1);
|
||||
m_Rs_base[mface] = m_a * m_Rs_base[mface] + (1 - m_a) * ia / ib;
|
||||
|
||||
ia = m_Ys[mface];
|
||||
ib = std::max(Ns,(uint64_t)1);
|
||||
m_Rs_ex[mface] = m_a * m_Rs_ex[mface] + (1 - m_a) * (Rs - ia / ib);
|
||||
|
||||
m_Ys_old[mface] = m_Ys[mface];
|
||||
|
||||
m_Yp[mface] = 0;
|
||||
m_Ys[mface] = 0;
|
||||
|
||||
|
||||
|
||||
}
|
||||
//在队列大小限制范围内的兴趣包,转发过程不会超时,这个功能暂时没用。
|
||||
/*
|
||||
void
|
||||
MIRCCStrategy::refreshQueueInterest(FaceEndpoint &ingress)
|
||||
{
|
||||
//清空face队列中过期的兴趣包
|
||||
auto now = time::steady_clock::now();
|
||||
|
||||
while (m_Queue[ingress].qp.size() > 0 and m_Queue[ingress].tp.front() < now)
|
||||
{
|
||||
m_Queue[ingress].qp.pop_front();
|
||||
m_Queue[ingress].tp.pop_front();
|
||||
}
|
||||
|
||||
while (m_Queue[ingress].qs.size() > 0 and m_Queue[ingress].ts.front() < now)
|
||||
{
|
||||
m_Queue[ingress].qs.pop_front();
|
||||
m_Queue[ingress].ts.pop_front();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
uint64_t
|
||||
MIRCCStrategy::getQt(FaceId mface)
|
||||
{
|
||||
|
||||
|
||||
//清除队列中过期兴趣包,避免造成干扰
|
||||
//refreshQueueInterest(mface);
|
||||
//返回兴趣包个数*兴趣包大小*数据包与兴趣包大小之比
|
||||
return (m_Queue[mface].qp.size() + m_Queue[mface].qs.size()) * INTEREST_SIZE * m_ratio[mface];
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MIRCCStrategy::pushQueueInterest(FaceId mface, const Interest &interest,const shared_ptr<pit::Entry>& pitEntry)
|
||||
{
|
||||
NS_LOG_DEBUG("MIRCC pushQueueInterest");
|
||||
|
||||
//更新Yt
|
||||
updateYt(mface,interest);
|
||||
|
||||
uint64_t p = *interest.getTag<lp::PTag>();
|
||||
//如果是第一类兴趣包
|
||||
if (p == 1)
|
||||
{
|
||||
//如果队列已经满了
|
||||
if (m_Queue[mface].qp.size() + m_Queue[mface].qs.size() >= QUEUE_MAX)
|
||||
{
|
||||
//如果存在第二类兴趣包可以删除
|
||||
if (m_Queue[mface].qs.size() > 0)
|
||||
{
|
||||
//删掉第二类兴趣包最后一个,把当前第一类兴趣包加入
|
||||
m_Queue[mface].qs.pop_back();
|
||||
m_Queue[mface].ts.pop_back();
|
||||
m_Queue[mface].ps.pop_back();
|
||||
m_Queue[mface].qp.push_back(const_cast<Interest&>(interest).shared_from_this());
|
||||
m_Queue[mface].tp.push_back(time::steady_clock::now());
|
||||
m_Queue[mface].pp.push_back(pitEntry);
|
||||
}else
|
||||
{
|
||||
//否则当前兴趣包丢失
|
||||
|
||||
//这里应该回传Nack,还没有写完
|
||||
}
|
||||
}else
|
||||
{
|
||||
//直接将当前兴趣包加入第一类兴趣包队列末尾
|
||||
m_Queue[mface].qp.push_back(const_cast<Interest&>(interest).shared_from_this());
|
||||
m_Queue[mface].tp.push_back(time::steady_clock::now());
|
||||
m_Queue[mface].pp.push_back(pitEntry);
|
||||
}
|
||||
}else
|
||||
{
|
||||
//如果队列已经满了
|
||||
if (m_Queue[mface].qp.size() + m_Queue[mface].qs.size() >= QUEUE_MAX)
|
||||
{
|
||||
//当前兴趣包丢失
|
||||
|
||||
//这里是否应该回传Nack不确定,需要回去看论文,第二类兴趣包处理方式似乎与第一类不同,还没有写完
|
||||
}else
|
||||
{
|
||||
//将但钱兴趣包加入第二类末尾
|
||||
m_Queue[mface].qs.push_back(const_cast<Interest&>(interest).shared_from_this());
|
||||
m_Queue[mface].ts.push_back(time::steady_clock::now());
|
||||
m_Queue[mface].ps.push_back(pitEntry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MIRCCStrategy::updateYt(FaceId mface, const Interest &interest)
|
||||
{
|
||||
|
||||
uint64_t p = *interest.getTag<lp::PTag>();
|
||||
if (p == 1)
|
||||
{
|
||||
m_Yp[mface] += INTEREST_SIZE * m_ratio[mface];
|
||||
}else
|
||||
{
|
||||
m_Ys[mface] += INTEREST_SIZE * m_ratio[mface];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MIRCCStrategy::afterReceiveInterest(const FaceEndpoint &ingress, const Interest &interest, const shared_ptr<pit::Entry> &pitEntry)
|
||||
{//目前在按照标识路径转发,采用MIRCC论文中的方法2
|
||||
NS_LOG_DEBUG("MIRCC afterReceiveInterest");
|
||||
|
||||
//MIRCC似乎不需要判断isNextHopEligible???
|
||||
//稍微有点不理解Out-record在干啥
|
||||
if (hasPendingOutRecords(*pitEntry))
|
||||
{
|
||||
//已经有记录,等待即可。
|
||||
//这个位置要不要在其他路径继续转发(比如pathid不相同的情况),不太确定
|
||||
//我记得原文是说不考虑任何的中间的cs命中之类的情况
|
||||
return;
|
||||
}
|
||||
|
||||
//根据hash值获取一个参考端口号,还需要根据可用端口数量进一步取模来最终选取转发端口。
|
||||
uint64_t tmpFace = chooseFaceForInterestByHash(interest);
|
||||
|
||||
const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
|
||||
|
||||
fib::NextHopList outFaces = fibEntry.getNextHops();
|
||||
|
||||
if (outFaces.size() != 0)
|
||||
{//如果存在端口可以转发
|
||||
uint64_t choosedFace = tmpFace % outFaces.size();
|
||||
Face& outFace = outFaces[choosedFace].getFace();
|
||||
//放入对应端口队列进行排队
|
||||
this->pushQueueInterest(outFace.getId(), interest, pitEntry);
|
||||
NS_LOG_DEBUG("MIRCC : outFace" << outFace.getId());
|
||||
return;
|
||||
}else
|
||||
{
|
||||
NS_LOG_DEBUG("MIRCC : outFace=0");
|
||||
}
|
||||
|
||||
//如果发现没有端口可以转发,则设置立马删除该条pit
|
||||
//后续Nack处理是否得当并不清楚,还需要研究
|
||||
lp::NackHeader nackHeader;
|
||||
nackHeader.setReason(lp::NackReason::NO_ROUTE);
|
||||
this->sendNack(pitEntry, ingress, nackHeader);
|
||||
this->rejectPendingInterest(pitEntry);
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MIRCCStrategy::afterReceiveNack(const FaceEndpoint &ingress, const lp::Nack &nack, const shared_ptr<pit::Entry> &pitEntry)
|
||||
{
|
||||
NS_LOG_DEBUG("MIRCC afterReceiveNack");
|
||||
//nack具体怎么处理还需要研究
|
||||
//nack应该利用预留给data的带宽,返回给consumer
|
||||
//Forwarder::onIncomingNack似乎已经把Nack返回给consumer了
|
||||
}
|
||||
|
||||
void
|
||||
MIRCCStrategy::beforeSatisfyInterest(const shared_ptr<pit::Entry> &pitEntry, const FaceEndpoint &ingress, const Data &data)
|
||||
{
|
||||
|
||||
NS_LOG_DEBUG("MIRCC beforeSatisfyInterest");
|
||||
auto now = time::steady_clock::now();
|
||||
//uint64_t rcd_cnt = 0;
|
||||
//目前计算中,只考虑没有过期的并成功收到数据包的兴趣包对RTT和ratio的影响,超时的数据包是否对RTT有影响?。
|
||||
for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
|
||||
if (inRecord.getExpiry() > now)
|
||||
{
|
||||
if (inRecord.getFace().getId() == ingress.face.getId() && inRecord.getFace().getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//计算收到数据包对数据包/兴趣包大小比率的影响
|
||||
m_ratio[ingress.face.getId()] = m_ratio_a * m_ratio[ingress.face.getId()] + (1 - m_ratio_a) * (data.getContent().size() / INTEREST_SIZE);
|
||||
|
||||
//计算收到数据包对RTT的影响。
|
||||
//时间计算存在重大问题
|
||||
// time::steady_clock::TimePoint tmpRTT = time::steady_clock::now() - inRecord.getLastRenewed();//不确定正确性,可能还要继续考虑
|
||||
// m_d[ingress.face] = m_rtt_a * m_d[ingress.face] + (1.0 - m_rtt_a) * tmpRTT.count();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint64_t
|
||||
MIRCCStrategy::fpow(uint64_t a,uint64_t k,uint64_t p)
|
||||
{
|
||||
|
||||
int64_t res = 1;
|
||||
while (k != 0)
|
||||
{
|
||||
if (k % 2 != 0)
|
||||
{
|
||||
res = res * a % p;
|
||||
}
|
||||
k >>= 1;
|
||||
a = a * a % p;
|
||||
}
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MIRCCStrategy::setHashForData(FaceId mface, const Data &data)
|
||||
{//注意!!HopCountTag的工作情况目前不太了解,似乎ndnsim这个Tag没做处理,后续需要考虑
|
||||
|
||||
NS_LOG_DEBUG("MIRCC setHashForData");
|
||||
//处理路径标识id
|
||||
auto oldPath = data.getTag<lp::PathidTag>();
|
||||
uint64_t hashOld;
|
||||
if (oldPath != nullptr)
|
||||
{
|
||||
hashOld = *data.getTag<lp::PathidTag>();
|
||||
}else{
|
||||
hashOld = 0;
|
||||
}
|
||||
//uint64_t hashNew = (hashOld + hashUnit[data.getTag<lp::HopCountTag>()] * mface.getFace().getId() % hashMo) % hashMo;
|
||||
//靠近producer的为hash值的高位
|
||||
uint64_t hashNew = (hashOld * hashNum % hashMo + mface % hashMo) % hashMo;
|
||||
//给data设置新的hash值
|
||||
|
||||
data.setTag(make_shared<lp::PathidTag>(hashNew));
|
||||
|
||||
}
|
||||
|
||||
uint64_t
|
||||
MIRCCStrategy::chooseFaceForInterestByHash(const Interest &interest)
|
||||
{
|
||||
NS_LOG_DEBUG("MIRCC chooseFaceForInterestByHash");
|
||||
uint64_t hashGuide = *interest.getTag<lp::PathidTag>();
|
||||
uint64_t Faceid = hashGuide % hashMo % hashNum;
|
||||
return Faceid;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MIRCCStrategy::afterReceiveData(const shared_ptr<pit::Entry> &pitEntry, const FaceEndpoint &ingress, const Data &data)
|
||||
{
|
||||
|
||||
NS_LOG_DEBUG("MIRCC afterReceiveData");
|
||||
setHashForData(ingress.face.getId(), data);
|
||||
|
||||
//修改Rt的值
|
||||
auto oldRp = data.getTag<lp::RpTag>();
|
||||
uint64_t dataRp;
|
||||
if (oldRp != nullptr)
|
||||
{
|
||||
dataRp = *data.getTag<lp::RpTag>();
|
||||
if (dataRp > m_Rp_base[ingress.face.getId()] + m_Rp_ex[ingress.face.getId()])
|
||||
{
|
||||
data.setTag(make_shared<lp::RpTag>(m_Rp_base[ingress.face.getId()] + m_Rp_ex[ingress.face.getId()]));
|
||||
}
|
||||
}else
|
||||
{
|
||||
data.setTag(make_shared<lp::RpTag>(m_Rp_base[ingress.face.getId()] + m_Rp_ex[ingress.face.getId()]));
|
||||
}
|
||||
|
||||
|
||||
auto oldRs = data.getTag<lp::RsTag>();
|
||||
uint64_t dataRs;
|
||||
if (oldRs != nullptr)
|
||||
{
|
||||
dataRs =*data.getTag<lp::RsTag>();
|
||||
if (dataRs > m_Rs_base[ingress.face.getId()] + m_Rs_ex[ingress.face.getId()])
|
||||
{
|
||||
data.setTag(make_shared<lp::RsTag>(m_Rs_base[ingress.face.getId()] + m_Rs_ex[ingress.face.getId()]));
|
||||
}
|
||||
}else
|
||||
{
|
||||
data.setTag(make_shared<lp::RsTag>(m_Rs_base[ingress.face.getId()] + m_Rs_ex[ingress.face.getId()]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
beforeSatisfyInterest(pitEntry, ingress, data);
|
||||
|
||||
sendDataToAll(pitEntry, ingress, data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
|
||||
#include "face/face.hpp"
|
||||
#include "fw/strategy.hpp"
|
||||
#include "fw/algorithm.hpp"
|
||||
#include "fw/process-nack-traits.hpp"
|
||||
#include <unordered_map>
|
||||
#include <limits>
|
||||
#include <deque>
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
#include "common/global.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
struct hash_Face
|
||||
{
|
||||
FaceId operator()(const Face &x) const
|
||||
{
|
||||
|
||||
return x.getId();
|
||||
}
|
||||
};
|
||||
|
||||
struct cmp_Face
|
||||
{
|
||||
bool operator()(const Face &x,const Face &y) const
|
||||
{
|
||||
return x.getId() == y.getId();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class MIRCCQueue
|
||||
{
|
||||
public:
|
||||
std:: deque<shared_ptr<Interest>> qp,qs;
|
||||
//记录的是过期时间,非达到时间
|
||||
std:: deque<time::steady_clock::TimePoint> tp,ts;
|
||||
|
||||
std:: deque<shared_ptr<pit::Entry>> pp,ps;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
MIRCC 策略实现
|
||||
*/
|
||||
class MIRCCStrategy : public Strategy, public ProcessNackTraits<MIRCCStrategy>
|
||||
{
|
||||
public:
|
||||
explicit MIRCCStrategy(Forwarder &forwarder, const ndn::Name &name);
|
||||
|
||||
~MIRCCStrategy() override = default;
|
||||
|
||||
void
|
||||
afterReceiveInterest(const FaceEndpoint &ingress, const Interest &interest,const shared_ptr<pit::Entry> &pitEntry) override;
|
||||
|
||||
void
|
||||
afterReceiveNack(const FaceEndpoint &ingress, const lp::Nack &nack,const shared_ptr<pit::Entry> &pitEntry) override;
|
||||
|
||||
void
|
||||
beforeSatisfyInterest(const shared_ptr<pit::Entry> &pitEntry,const FaceEndpoint &ingress, const Data &data) override;
|
||||
|
||||
void
|
||||
afterReceiveData(const shared_ptr<pit::Entry> &pitEntry,const FaceEndpoint &ingress, const Data &data) override;
|
||||
|
||||
/**
|
||||
* 获取最大的目标速率
|
||||
* @return
|
||||
*/
|
||||
static uint64_t
|
||||
getMaxR()
|
||||
{
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
|
||||
static const Name &
|
||||
getStrategyName();
|
||||
|
||||
protected:
|
||||
friend ProcessNackTraits<MIRCCStrategy>;
|
||||
|
||||
private:
|
||||
std::unordered_map<uint64_t,uint64_t> m_Rp_base;//Rp的base速率
|
||||
std::unordered_map<uint64_t,uint64_t> m_Rp_ex;//Rp的ex速率
|
||||
std::unordered_map<uint64_t,uint64_t> m_Rs_base;//Rs的base速率
|
||||
std::unordered_map<uint64_t,uint64_t> m_Rs_ex;//Rs的ex速率
|
||||
std::unordered_map<uint64_t,uint64_t> m_Yp;//本周期的Yp(t)
|
||||
std::unordered_map<uint64_t,uint64_t> m_Yp_old;//上一个周期的Yp(t)
|
||||
std::unordered_map<uint64_t,uint64_t> m_Ys;//本周起的Ys(t)
|
||||
std::unordered_map<uint64_t,uint64_t> m_Ys_old;//上一个周期的Ys(t)
|
||||
std::unordered_map<uint64_t,uint64_t> m_d;//维护每一个face的RTT
|
||||
std::unordered_map<uint64_t,MIRCCQueue> m_Queue;//用于出口排队转发兴趣包
|
||||
std::unordered_map<uint64_t,uint64_t> m_ratio;//维护每一个face的Data/Interest
|
||||
//这个大小之比要按照第一类,第二类进行分类么?
|
||||
std::unordered_map<uint64_t,uint64_t> m_linkC;//每一个链路的带宽,目前不知道怎么获取,都设置为10 * 1000 * 1000 * 8
|
||||
|
||||
//通过兴趣包标注的path来获得对应的转发端口
|
||||
//采用MIRCC论文中提出的第二个方案,由consumer随机生成hash值来引导转发,路由器无需在记录对应关系
|
||||
//unorderer_map<unint64_t,FaceEndPoint> pathid2face;
|
||||
|
||||
//兴趣包大小常量
|
||||
const uint64_t INTEREST_SIZE = 300;
|
||||
//队列大小常量
|
||||
const uint64_t QUEUE_MAX = 1000;
|
||||
|
||||
const double m_B = 0.1,m_a = 0.5,m_miu = 0.95,m_ratio_a = 0.99 ,m_rtt_a = 0.99;
|
||||
|
||||
uint64_t hashUnit[100],hashMo = 998244353,hashNum = 37,invMod = 0;
|
||||
|
||||
|
||||
//发送对应端口1个正在排队的兴趣包,并设置下一次发送时间
|
||||
void
|
||||
sendQueueInterest(FaceId mface);
|
||||
|
||||
//清空对应端口队列中所有过期的兴趣包
|
||||
//void
|
||||
//refreshQueueInterest(Face &ingress);
|
||||
|
||||
//将兴趣包放入对应端口的队列
|
||||
void
|
||||
pushQueueInterest(FaceId mface, const Interest &interest,const shared_ptr<pit::Entry>& pitEntry);
|
||||
|
||||
//计算并返回q(t)
|
||||
uint64_t
|
||||
getQt(FaceId mface);
|
||||
|
||||
//计算Rt
|
||||
void
|
||||
calcRt(FaceId mface);
|
||||
|
||||
//更新Yt
|
||||
void
|
||||
updateYt(FaceId mface, const Interest &interest);
|
||||
|
||||
void
|
||||
setHashForData(FaceId mface, const Data &data);
|
||||
|
||||
|
||||
uint64_t
|
||||
chooseFaceForInterestByHash(const Interest &interest);
|
||||
|
||||
uint64_t
|
||||
fpow(uint64_t a,uint64_t k,uint64_t p);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -40,15 +40,13 @@ namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
NFD_LOG_INIT(SelfLearningStrategy);
|
||||
//NFD_REGISTER_STRATEGY(SelfLearningStrategy);
|
||||
NFD_REGISTER_STRATEGY(SelfLearningStrategy);
|
||||
|
||||
const time::milliseconds SelfLearningStrategy::ROUTE_RENEW_LIFETIME(10_min);
|
||||
|
||||
SelfLearningStrategy::SelfLearningStrategy(Forwarder& forwarder, const Name& name)
|
||||
: Strategy(forwarder)
|
||||
{
|
||||
NS_LOG_DEBUG("trueinit");
|
||||
printf("trueinit\n");
|
||||
ParsedInstanceName parsed = parseInstanceName(name);
|
||||
if (!parsed.parameters.empty()) {
|
||||
NDN_THROW(std::invalid_argument("SelfLearningStrategy does not accept parameters"));
|
||||
@@ -105,8 +103,6 @@ void
|
||||
SelfLearningStrategy::afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& ingress, const Data& data)
|
||||
{
|
||||
NS_LOG_DEBUG("trueself");
|
||||
printf("trueselff\n");
|
||||
auto outRecord = pitEntry->getOutRecord(ingress.face);
|
||||
if (outRecord == pitEntry->out_end()) {
|
||||
NFD_LOG_DEBUG("Data " << data.getName() << " from=" << ingress << " no out-record");
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "common/logger.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/pit-token.hpp>
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
#include <boost/range/algorithm/copy.hpp>
|
||||
@@ -232,6 +233,12 @@ Strategy::sendData(const shared_ptr<pit::Entry>& pitEntry, const Data& data,
|
||||
auto inRecord = pitEntry->getInRecord(egress.face);
|
||||
if (inRecord != pitEntry->in_end()) {
|
||||
pitToken = inRecord->getInterest().getTag<lp::PitToken>();
|
||||
|
||||
// 把兴趣包中的 CongestionTag 传递给对应的数据包
|
||||
auto congestionTag = inRecord->getInterest().getTag<ndn::lp::CongestionMarkTag>();
|
||||
if (congestionTag != nullptr) {
|
||||
data.setTag(congestionTag);
|
||||
}
|
||||
}
|
||||
|
||||
// delete the PIT entry's in-record based on egress,
|
||||
|
||||
@@ -40,8 +40,7 @@ Entry::canMatch(const Interest& interest, size_t nEqualNameComps) const
|
||||
{
|
||||
BOOST_ASSERT(m_interest->getName().compare(0, nEqualNameComps,
|
||||
interest.getName(), 0, nEqualNameComps) == 0);
|
||||
printf("boost finish%d %d %d\n",m_interest->getName().compare(nEqualNameComps, Name::npos,
|
||||
interest.getName(), nEqualNameComps) == 0,m_interest->getCanBePrefix() == interest.getCanBePrefix(),m_interest->getMustBeFresh() == interest.getMustBeFresh());
|
||||
|
||||
return m_interest->getName().compare(nEqualNameComps, Name::npos,
|
||||
interest.getName(), nEqualNameComps) == 0 &&
|
||||
m_interest->getCanBePrefix() == interest.getCanBePrefix() &&
|
||||
|
||||
@@ -1,363 +0,0 @@
|
||||
|
||||
|
||||
#include "mircc-consumer.hpp"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/integer.h"
|
||||
#include "ns3/double.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("ndn.ConsumerMIRCC");
|
||||
|
||||
namespace ns3 {
|
||||
namespace ndn {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(ConsumerMIRCC);
|
||||
|
||||
TypeId
|
||||
ConsumerMIRCC::GetTypeId(void)
|
||||
{
|
||||
static TypeId tid =
|
||||
TypeId("ns3::ndn::ConsumerMIRCC")
|
||||
.SetGroupName("Ndn")
|
||||
.SetParent<Consumer>()
|
||||
.AddConstructor<ConsumerMIRCC>()
|
||||
|
||||
.AddAttribute("MaxSeq", "Maximum sequence number to request",
|
||||
IntegerValue(std::numeric_limits<uint32_t>::max()),
|
||||
MakeIntegerAccessor(&ConsumerMIRCC::m_seqMax), MakeIntegerChecker<uint32_t>())
|
||||
|
||||
;
|
||||
|
||||
return tid;
|
||||
}
|
||||
|
||||
ConsumerMIRCC::ConsumerMIRCC()
|
||||
: m_frequency(1.0)
|
||||
, m_firstTime(true)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
m_seqMax = std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
|
||||
ConsumerMIRCC::~ConsumerMIRCC()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ConsumerMIRCC::ScheduleNextPacket()
|
||||
{
|
||||
std::printf("");
|
||||
// double mean = 8.0 * m_payloadSize / m_desiredRate.GetBitRate ();
|
||||
// std::cout << "next: " << Simulator::Now().ToDouble(Time::S) + mean << "s\n";
|
||||
/*
|
||||
if (m_firstTime) {
|
||||
m_sendEvent = Simulator::Schedule(Seconds(0.0), &Consumer::, this);
|
||||
m_firstTime = false;
|
||||
}
|
||||
else if (!m_sendEvent.IsRunning())
|
||||
m_sendEvent = Simulator::Schedule((m_random == 0) ? Seconds(1.0 / m_frequency)
|
||||
: Seconds(m_random->GetValue()),
|
||||
&Consumer::SendPacket, this);*/
|
||||
}
|
||||
|
||||
void
|
||||
ConsumerMIRCC:: StopApplication()
|
||||
{
|
||||
//获取发送事件表的迭代器
|
||||
auto it = pathId2EventId.begin();
|
||||
|
||||
//遍历发送事件表
|
||||
while(it != pathId2EventId.end())
|
||||
{
|
||||
//取消发送事件
|
||||
EventId tmp = it->second;
|
||||
Simulator::Cancel(tmp);
|
||||
|
||||
//迭代器后移
|
||||
it++;
|
||||
}
|
||||
Simulator::Cancel(explore_event);
|
||||
// 调用父类停止face等接口服务
|
||||
App::StopApplication();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ConsumerMIRCC:: StartApplication()
|
||||
{
|
||||
|
||||
// 调用父类开启face等接口服务
|
||||
App::StartApplication();
|
||||
|
||||
// 调用路径探索
|
||||
if (pathId2RandomId.size() == 0)
|
||||
{//如果节点刚开始运行
|
||||
//尝试利用随机数探索路径
|
||||
PathExplorate();
|
||||
explore_event = Simulator::Schedule(Seconds(1.0), &ConsumerMIRCC::PathExplorate, this);
|
||||
}else
|
||||
{//如果节点之前运行过,可以直接开始发送
|
||||
|
||||
//获取pahtid2RandomId的迭代器,用来遍历所有的随机路径数
|
||||
auto it = pathId2RandomId.begin();
|
||||
|
||||
while (it != pathId2RandomId.end())
|
||||
{
|
||||
//为这条PathId子流发送兴趣包
|
||||
SchedulePacketForPathId(it->first,1);
|
||||
SchedulePacketForPathId(it->first,2);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConsumerMIRCC ::recordSeq(uint64_t seq,uint64_t randId)
|
||||
{//记录seq到当时使用的randId
|
||||
seq2RandomId[seq] = randId;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ConsumerMIRCC ::SendPacket(uint64_t pathId,uint64_t classId)
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
NS_LOG_DEBUG("MIRCC SendPacket");
|
||||
uint32_t seq = std::numeric_limits<uint32_t>::max(); // invalid
|
||||
|
||||
//处理重传兴趣包
|
||||
//所以重传未必是用之前的子流重传,可能是新的子流
|
||||
//所以重传的兴趣包为一类还是二类完全随机,目前没有固定策略
|
||||
while (m_retxSeqs.size())
|
||||
{
|
||||
//取出第一个要重传的兴趣包
|
||||
seq = *m_retxSeqs.begin();
|
||||
//从重传队列删除
|
||||
m_retxSeqs.erase(m_retxSeqs.begin());
|
||||
break;
|
||||
}
|
||||
|
||||
if (seq == std::numeric_limits<uint32_t>::max())
|
||||
{//如果没有需要重传的数据包
|
||||
if (m_seqMax != std::numeric_limits<uint32_t>::max())
|
||||
{
|
||||
if (m_seq >= m_seqMax)
|
||||
{//已经把需要的序列号兴趣包都发完了
|
||||
return; // we are totally done
|
||||
}
|
||||
}
|
||||
|
||||
//没有重传数据包的前提下,顺次获取下一个需要发送的序号
|
||||
seq = m_seq++;
|
||||
}
|
||||
|
||||
//
|
||||
shared_ptr<Name> nameWithSequence = make_shared<Name>(m_interestName);
|
||||
nameWithSequence->appendSequenceNumber(seq);
|
||||
//
|
||||
|
||||
// shared_ptr<Interest> interest = make_shared<Interest> ();
|
||||
shared_ptr<Interest> interest = make_shared<Interest>();
|
||||
interest->setNonce(m_rand->GetValue(0, std::numeric_limits<uint32_t>::max()));
|
||||
interest->setName(*nameWithSequence);
|
||||
interest->setCanBePrefix(false);
|
||||
time::milliseconds interestLifeTime(m_interestLifeTime.GetMilliSeconds());
|
||||
interest->setInterestLifetime(interestLifeTime);
|
||||
|
||||
//获取对应PathId(子流)对应的RandId。
|
||||
uint64_t tmpRandId = pathId2RandomId[pathId];
|
||||
//将RandId作为Tag设置到interest包中。
|
||||
interest->setTag(make_shared<lp::PathidTag>(tmpRandId));
|
||||
interest->setTag(make_shared<lp::PTag>(classId));
|
||||
|
||||
//如果判断发现是随机数探索,则记录seq和随机数,用来收到data后把随机数和pathid绑定。
|
||||
if (pathId == 0)
|
||||
{
|
||||
recordSeq(seq,tmpRandId);
|
||||
}
|
||||
|
||||
|
||||
WillSendOutInterest(seq);
|
||||
|
||||
m_transmittedInterests(interest, this, m_face);
|
||||
m_appLink->onReceiveInterest(*interest);
|
||||
|
||||
//这个函数只负责发包,不在负责调用下一个包的发送
|
||||
//ScheduleNextPacket();
|
||||
}
|
||||
|
||||
uint64_t
|
||||
ConsumerMIRCC:: SumRp()
|
||||
{
|
||||
//获取遍历所有Rp的迭代器
|
||||
auto it = pathId2Rp.begin();
|
||||
uint64_t res = 0;
|
||||
//遍历所有Rp的迭代器
|
||||
while (it != pathId2Rp.end())
|
||||
{
|
||||
res += it->second;
|
||||
it++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
ConsumerMIRCC:: MaxRp()
|
||||
{
|
||||
//获取遍历所有Rp的迭代器
|
||||
auto it = pathId2Rp.begin();
|
||||
uint64_t res = 0;
|
||||
//遍历所有Rp的迭代器
|
||||
while (it != pathId2Rp.end())
|
||||
{
|
||||
res = std::max(res,it->second);
|
||||
it++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
ConsumerMIRCC:: SchedulePacketForPathId(uint64_t pathId,uint64_t classId)
|
||||
{
|
||||
SendPacket(pathId,classId);
|
||||
if (classId == 1)
|
||||
{//发送第一类兴趣包,参考当先path的Rp在所有Rp之和的占比 乘上最大Rp
|
||||
//计算发送速度
|
||||
uint64_t tmpRp = pathId2Rp[pathId] / std::max(SumRp() * MaxRp(),(uint64_t)1);
|
||||
//发送
|
||||
SendPacket(pathId,classId);
|
||||
//预定下一次发送事件
|
||||
//pathId2EventId[pathId] = Simulator::Schedule(time::seconds(INTEREST_SIZE / std::max(tmpRp,INTEREST_SIZE)), bind(&ConsumerMIRCC::SchedulePacketForPathId,this, pathId,classId));
|
||||
pathId2EventId[pathId] = Simulator::Schedule(Seconds((double)INTEREST_SIZE / std::max(tmpRp,INTEREST_SIZE)), &ConsumerMIRCC::SchedulePacketForPathId,this, pathId,classId);
|
||||
}else
|
||||
{//发送第二类兴趣包
|
||||
uint64_t tmpRs = pathId2Rs[pathId];
|
||||
//发送
|
||||
SendPacket(pathId,classId);
|
||||
//预定下一次发送事件
|
||||
//pathId2EventId[pathId] = Simulator::Schedule(time::seconds(INTEREST_SIZE / std::max(tmpRs,INTEREST_SIZE)), bind(&ConsumerMIRCC::SchedulePacketForPathId, this, pathId,classId));
|
||||
pathId2EventId[pathId] = Simulator::Schedule(Seconds((double)INTEREST_SIZE / std::max(tmpRs,INTEREST_SIZE)), &ConsumerMIRCC::SchedulePacketForPathId, this, pathId,classId);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ConsumerMIRCC:: PathExplorate()
|
||||
{
|
||||
//路径探索的兴趣包全部标为第一类,原论文没有明确说,但是我觉得这样更合理
|
||||
//因为用于路径探索的兴趣包很重要,如果被丢掉了,consumer可能迟迟无法开始正式发送兴趣包
|
||||
pathId2RandomId[0] = m_rand->GetValue(0.00001, std::numeric_limits<uint32_t>::max());
|
||||
|
||||
//PathId为-1表示正在进行路径探索
|
||||
SendPacket(0,1);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ConsumerMIRCC::tryBindRandId(uint64_t seq, uint64_t pathId)
|
||||
{
|
||||
if (seq2RandomId.find(seq) == seq2RandomId.end())
|
||||
{
|
||||
//没有找到seq对应的需要绑定的pathId
|
||||
return;
|
||||
}
|
||||
|
||||
if (pathId2RandomId.find(pathId) != pathId2RandomId.end())
|
||||
{
|
||||
//随机数对应了一条已经找到对应随机数的pathid,没有发现新路径
|
||||
return;
|
||||
}
|
||||
//将随机数绑定到pathid上
|
||||
pathId2RandomId[pathId] = seq2RandomId[seq];
|
||||
//开启新路径
|
||||
//为找到的新路径安排发送事件
|
||||
SchedulePacketForPathId(pathId,1);
|
||||
SchedulePacketForPathId(pathId,2);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ConsumerMIRCC::OnData(shared_ptr<const Data> data)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << data);
|
||||
if (!m_active)
|
||||
return;
|
||||
|
||||
App::OnData(data); // tracing inside
|
||||
|
||||
NS_LOG_FUNCTION(this << data);
|
||||
|
||||
|
||||
// NS_LOG_INFO ("Received content object: " << boost::cref(*data));
|
||||
|
||||
// This could be a problem......
|
||||
uint32_t seq = data->getName().at(-1).toSequenceNumber();
|
||||
NS_LOG_INFO("< DATA for " << seq);
|
||||
|
||||
//查看当前数据包是否有探索兴趣包产生,如果是的话将探索出的pathid和对应的randId绑定
|
||||
printf("pathid IN");
|
||||
auto tmpPathid = data->getTag<lp::PathidTag>();
|
||||
if (tmpPathid != nullptr)
|
||||
{
|
||||
tryBindRandId(seq, *tmpPathid);
|
||||
}
|
||||
printf("pathid OUT");
|
||||
|
||||
|
||||
int hopCount = 0;
|
||||
auto hopCountTag = data->getTag<lp::HopCountTag>();
|
||||
if (hopCountTag != nullptr) { // e.g., packet came from local node's cache
|
||||
hopCount = *hopCountTag;
|
||||
}
|
||||
NS_LOG_DEBUG("Hop count!!: " << hopCount);
|
||||
|
||||
|
||||
uint64_t Rp = 0;
|
||||
auto rpTag = data->getTag<lp::RpTag>();
|
||||
if (rpTag != nullptr)
|
||||
{
|
||||
Rp = *rpTag;
|
||||
}
|
||||
pathId2Rp[*tmpPathid] = Rp;
|
||||
NS_LOG_INFO("Rp: " << Rp);
|
||||
|
||||
uint64_t Rs = 0;
|
||||
auto rsTag = data->getTag<lp::RsTag>();
|
||||
if (rsTag != nullptr)
|
||||
{
|
||||
Rs = *rsTag;
|
||||
}
|
||||
pathId2Rs[*tmpPathid] = Rs;
|
||||
NS_LOG_INFO("Rs: " << Rs);
|
||||
|
||||
SeqTimeoutsContainer::iterator entry = m_seqLastDelay.find(seq);
|
||||
if (entry != m_seqLastDelay.end()) {
|
||||
m_lastRetransmittedInterestDataDelay(this, seq, Simulator::Now() - entry->time, hopCount);
|
||||
}
|
||||
|
||||
entry = m_seqFullDelay.find(seq);
|
||||
if (entry != m_seqFullDelay.end()) {
|
||||
m_firstInterestDataDelay(this, seq, Simulator::Now() - entry->time, m_seqRetxCounts[seq], hopCount);
|
||||
}
|
||||
|
||||
m_seqRetxCounts.erase(seq);
|
||||
m_seqFullDelay.erase(seq);
|
||||
m_seqLastDelay.erase(seq);
|
||||
|
||||
m_seqTimeouts.erase(seq);
|
||||
m_retxSeqs.erase(seq);
|
||||
|
||||
m_rtt->AckSeq(SequenceNumber32(seq));
|
||||
}
|
||||
|
||||
} // namespace ndn
|
||||
} // namespace ns3
|
||||
@@ -1,113 +0,0 @@
|
||||
|
||||
|
||||
#ifndef NDN_CONSUMER_MIRCC_H
|
||||
#define NDN_CONSUMER_MIRCC_H
|
||||
|
||||
#include "ns3/ndnSIM/model/ndn-common.hpp"
|
||||
|
||||
#include "ndn-consumer.hpp"
|
||||
#include <unordered_map>
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
|
||||
|
||||
namespace ns3 {
|
||||
namespace ndn {
|
||||
|
||||
/**
|
||||
* @ingroup ndn-apps
|
||||
* @brief Ndn application for sending out Interest packets at a "constant" rate (Poisson process)
|
||||
*/
|
||||
class ConsumerMIRCC : public Consumer {
|
||||
public:
|
||||
static TypeId
|
||||
GetTypeId();
|
||||
|
||||
/**
|
||||
* \brief Default constructor
|
||||
* Sets up randomizer function and packet sequence number
|
||||
*/
|
||||
ConsumerMIRCC();
|
||||
virtual ~ConsumerMIRCC();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Constructs the Interest packet and sends it using a callback to the underlying NDN
|
||||
* protocol
|
||||
*/
|
||||
virtual void
|
||||
ScheduleNextPacket();
|
||||
|
||||
|
||||
void
|
||||
StopApplication() override;
|
||||
//相比原有的consumer,MIRCC多个子流同时发送,存在一个eventid表需要关闭。
|
||||
|
||||
void
|
||||
StartApplication() override;
|
||||
//相比原有的consumer,MIRCC第一步为先探索路径,而非直接发送
|
||||
|
||||
//void
|
||||
//SendPacket(uint64_t pathId) override;
|
||||
|
||||
void
|
||||
OnData(shared_ptr<const Data> data) override;
|
||||
|
||||
protected:
|
||||
//这两个目前没有用处
|
||||
double m_frequency; // Frequency of interest packets (in hertz)
|
||||
bool m_firstTime;
|
||||
//
|
||||
Ptr<RandomVariableStream> m_random;
|
||||
std::string m_randomType;
|
||||
|
||||
private:
|
||||
//路径id到发送事件id的一一映射关系
|
||||
std:: unordered_map <uint64_t,EventId> pathId2EventId;
|
||||
|
||||
//路径id到路径随机数的一一映射关系(使用对应路径随机数使得路由器按该路径转发)
|
||||
std:: unordered_map <uint64_t,uint64_t> pathId2RandomId;
|
||||
|
||||
//路径id到该路径Rp的一一映射关系
|
||||
std:: unordered_map <uint64_t,uint64_t> pathId2Rp;
|
||||
|
||||
//路径id到该路径Rs的一一映射关系
|
||||
std:: unordered_map <uint64_t,uint64_t> pathId2Rs;
|
||||
|
||||
//
|
||||
std:: unordered_map <uint64_t,uint64_t> seq2RandomId;
|
||||
|
||||
|
||||
const uint64_t INTEREST_SIZE = 300;
|
||||
|
||||
//利用随机数探索路径
|
||||
void PathExplorate();
|
||||
|
||||
//使用pathId发送
|
||||
void SchedulePacketForPathId(uint64_t pathId,uint64_t classId);
|
||||
|
||||
//计算所有Rp的速率之和
|
||||
uint64_t SumRp();
|
||||
|
||||
|
||||
//计算所有Rp的速率最大值
|
||||
uint64_t MaxRp();
|
||||
|
||||
//记录seq号和随机数,用于绑定pathid和randid。
|
||||
void recordSeq();
|
||||
|
||||
void tryBindRandId(uint64_t seq, uint64_t pathId);
|
||||
|
||||
void recordSeq(uint64_t seq,uint64_t randId);
|
||||
|
||||
void SendPacket(uint64_t pathId,uint64_t classId);
|
||||
|
||||
EventId explore_event;
|
||||
};
|
||||
|
||||
|
||||
//注意,目前版本的consumer假设所有节点的FIB不产生变化,否则会产生大量的路径判断未知问题!!!
|
||||
|
||||
} // namespace ndn
|
||||
} // namespace ns3
|
||||
|
||||
#endif
|
||||
@@ -130,7 +130,7 @@ ConsumerPcon::OnData(shared_ptr<const Data> data)
|
||||
m_inFlight--;
|
||||
}
|
||||
|
||||
NS_LOG_DEBUG("Window: " << m_window << ", InFlight: " << m_inFlight);
|
||||
//NS_LOG_DEBUG("Window: " << m_window << ", InFlight: " << m_inFlight);
|
||||
|
||||
ScheduleNextPacket();
|
||||
}
|
||||
@@ -144,7 +144,7 @@ ConsumerPcon::OnTimeout(uint32_t sequenceNum)
|
||||
m_inFlight--;
|
||||
}
|
||||
|
||||
NS_LOG_DEBUG("Window: " << m_window << ", InFlight: " << m_inFlight);
|
||||
//NS_LOG_DEBUG("Window: " << m_window << ", InFlight: " << m_inFlight);
|
||||
|
||||
Consumer::OnTimeout(sequenceNum);
|
||||
}
|
||||
@@ -169,7 +169,7 @@ ConsumerPcon::WindowIncrease()
|
||||
else {
|
||||
BOOST_ASSERT_MSG(false, "Unknown CC Algorithm");
|
||||
}
|
||||
NS_LOG_DEBUG("Window size increased to " << m_window);
|
||||
//NS_LOG_DEBUG("Window size increased to " << m_window);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/ndnSIM-module.h"
|
||||
namespace ns3 {
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
AnnotatedTopologyReader topologyReader("", 25);
|
||||
topologyReader.SetFileName("topologies/topo-6-node.txt");
|
||||
topologyReader.Read();
|
||||
|
||||
// Install NDN stack on all nodes
|
||||
ndn::StackHelper ndnHelper;
|
||||
ndnHelper.setPolicy("nfd::cs::lru");
|
||||
ndnHelper.setCsSize(10000);
|
||||
ndnHelper.InstallAll();
|
||||
|
||||
// Choosing forwarding strategy
|
||||
ndn::StrategyChoiceHelper::InstallAll("/", "/localhost/nfd/strategy/best-route");
|
||||
|
||||
// Installing global routing interface on all nodes
|
||||
ndn::GlobalRoutingHelper ndnGlobalRoutingHelper;
|
||||
ndnGlobalRoutingHelper.InstallAll();
|
||||
|
||||
// Getting containers for the consumer/producer
|
||||
Ptr<Node> consumer1 = Names::Find<Node>("Src1");
|
||||
Ptr<Node> consumer2 = Names::Find<Node>("Src2");
|
||||
|
||||
Ptr<Node> producer1 = Names::Find<Node>("Dst1");
|
||||
Ptr<Node> producer2 = Names::Find<Node>("Dst2");
|
||||
|
||||
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerMIRCC");
|
||||
//consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second
|
||||
|
||||
// on the first consumer node install a Consumer application
|
||||
// that will express interests in /dst1 namespace
|
||||
consumerHelper.SetPrefix("/dst1");
|
||||
consumerHelper.Install(consumer1);
|
||||
|
||||
// on the second consumer node install a Consumer application
|
||||
// that will express interests in /dst2 namespace
|
||||
consumerHelper.SetPrefix("/dst2");
|
||||
//consumerHelper.SetAttribute("Frequency", StringValue("500")); // 100 interests a second
|
||||
consumerHelper.Install(consumer2);
|
||||
|
||||
ndn::AppHelper producerHelper("ns3::ndn::Producer");
|
||||
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
|
||||
|
||||
// Register /dst1 prefix with global routing controller and
|
||||
// install producer that will satisfy Interests in /dst1 namespace
|
||||
ndnGlobalRoutingHelper.AddOrigins("/dst1", producer1);
|
||||
producerHelper.SetPrefix("/dst1");
|
||||
producerHelper.Install(producer1);
|
||||
|
||||
// Register /dst2 prefix with global routing controller and
|
||||
// install producer that will satisfy Interests in /dst2 namespace
|
||||
ndnGlobalRoutingHelper.AddOrigins("/dst2", producer2);
|
||||
producerHelper.SetPrefix("/dst2");
|
||||
producerHelper.Install(producer2);
|
||||
|
||||
// Calculate and install FIBs
|
||||
ndn::GlobalRoutingHelper::CalculateRoutes();
|
||||
|
||||
Simulator::Stop(Seconds(20.0));
|
||||
|
||||
ndn::L3RateTracer::InstallAll("rate-trace.txt", Seconds(0.5));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
return ns3::main(argc, argv);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/ndnSIM-module.h"
|
||||
#include "../src/ndnSIM/NFD/daemon/fw/mircc-strategy.hpp"
|
||||
#include "../src/ndnSIM/NFD/daemon/fw/self-learning-strategy.hpp"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
@@ -63,9 +62,7 @@ main(int argc, char* argv[])
|
||||
ndnHelper.InstallAll();
|
||||
|
||||
// Choosing forwarding strategy
|
||||
ndn::StrategyChoiceHelper::InstallAll<nfd::fw::MIRCCStrategy>("/");
|
||||
//ndn::StrategyChoiceHelper::InstallAll<nfd::fw::SelfLearningStrategy>("/prefix");
|
||||
//ndn::StrategyChoiceHelper::InstallAll("/prefix", "/localhost/nfd/strategy/best-route-strategy");
|
||||
ndn::StrategyChoiceHelper::InstallAll("/prefix", "/localhost/nfd/strategy/best-route");
|
||||
|
||||
// Installing global routing interface on all nodes
|
||||
ndn::GlobalRoutingHelper ndnGlobalRoutingHelper;
|
||||
@@ -78,9 +75,8 @@ main(int argc, char* argv[])
|
||||
Ptr<Node> producer1 = Names::Find<Node>("Dst1");
|
||||
Ptr<Node> producer2 = Names::Find<Node>("Dst2");
|
||||
|
||||
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerMIRCC");
|
||||
//ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
|
||||
consumerHelper.SetAttribute("MaxSeq", StringValue("10000000")); // 100 interests a second
|
||||
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
|
||||
consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second
|
||||
|
||||
// on the first consumer node install a Consumer application
|
||||
// that will express interests in /dst1 namespace
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2011-2015 Regents of the University of California.
|
||||
*
|
||||
* This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
|
||||
* contributors.
|
||||
*
|
||||
* ndnSIM is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ndnSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
// ndn-congestion-topo-plugin.cpp
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/ndnSIM-module.h"
|
||||
#include "../src/ndnSIM/NFD/daemon/fw/mircc-strategy.hpp"
|
||||
#include "../src/ndnSIM/NFD/daemon/fw/self-learning-strategy.hpp"
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This scenario simulates a grid topology (using topology reader module)
|
||||
*
|
||||
* /------\ /------\
|
||||
* | Src1 |<--+ +-->| Dst1 |
|
||||
* \------/ \ / \------/
|
||||
* \ /
|
||||
* +-->/------\ "bottleneck" /------\<-+
|
||||
* | Rtr1 |<===============>| Rtr2 |
|
||||
* +-->\------/ \------/<-+
|
||||
* / \
|
||||
* /------\ / \ /------\
|
||||
* | Src2 |<--+ +-->| Dst2 |
|
||||
* \------/ \------/
|
||||
*
|
||||
* To run scenario and see what is happening, use the following command:
|
||||
*
|
||||
* NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-congestion-topo-plugin
|
||||
*/
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
AnnotatedTopologyReader topologyReader("", 25);
|
||||
topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-4-node.txt");
|
||||
topologyReader.Read();
|
||||
|
||||
// Install NDN stack on all nodes
|
||||
ndn::StackHelper ndnHelper;
|
||||
ndnHelper.setPolicy("nfd::cs::lru");
|
||||
ndnHelper.setCsSize(10000);
|
||||
ndnHelper.InstallAll();
|
||||
|
||||
// Choosing forwarding strategy
|
||||
ndn::StrategyChoiceHelper::InstallAll<nfd::fw::MIRCCStrategy>("/");
|
||||
//ndn::StrategyChoiceHelper::InstallAll<nfd::fw::SelfLearningStrategy>("/prefix");
|
||||
//ndn::StrategyChoiceHelper::InstallAll("/prefix", "/localhost/nfd/strategy/best-route-strategy");
|
||||
|
||||
// Installing global routing interface on all nodes
|
||||
ndn::GlobalRoutingHelper ndnGlobalRoutingHelper;
|
||||
ndnGlobalRoutingHelper.InstallAll();
|
||||
|
||||
// Getting containers for the consumer/producer
|
||||
Ptr<Node> consumer1 = Names::Find<Node>("Src1");
|
||||
|
||||
Ptr<Node> producer1 = Names::Find<Node>("Dst1");
|
||||
|
||||
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerMIRCC");
|
||||
//ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
|
||||
consumerHelper.SetAttribute("MaxSeq", StringValue("10000000")); // 100 interests a second
|
||||
|
||||
// on the first consumer node install a Consumer application
|
||||
// that will express interests in /dst1 namespace
|
||||
consumerHelper.SetPrefix("/dst1");
|
||||
consumerHelper.Install(consumer1);
|
||||
|
||||
ndn::AppHelper producerHelper("ns3::ndn::Producer");
|
||||
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
|
||||
|
||||
// Register /dst1 prefix with global routing controller and
|
||||
// install producer that will satisfy Interests in /dst1 namespace
|
||||
ndnGlobalRoutingHelper.AddOrigins("/dst1", producer1);
|
||||
producerHelper.SetPrefix("/dst1");
|
||||
producerHelper.Install(producer1);
|
||||
|
||||
// Calculate and install FIBs
|
||||
ndn::GlobalRoutingHelper::CalculateRoutes();
|
||||
|
||||
Simulator::Stop(Seconds(20.0));
|
||||
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
return ns3::main(argc, argv);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
# topo-4-node.txt
|
||||
# /------\0 /------\3
|
||||
# | Src1 |<--+ +-->| Dst1 |
|
||||
# \------/ \ / \------/
|
||||
# \ /
|
||||
# +-->/------\1 "bottleneck" /------\2<-+
|
||||
# | Rtr1 |<===============>| Rtr2 |
|
||||
# \------/ \------/
|
||||
|
||||
|
||||
router
|
||||
|
||||
# node comment yPos xPos
|
||||
Src1 NA 1 3
|
||||
Rtr1 NA 2 5
|
||||
Rtr2 NA 2 7
|
||||
Dst1 NA 1 9
|
||||
|
||||
link
|
||||
|
||||
# srcNode dstNode bandwidth metric delay queue
|
||||
Src1 Rtr1 10Mbps 1 10ms 20
|
||||
Rtr1 Rtr2 1Mbps 1 10ms 20
|
||||
Dst1 Rtr2 10Mbps 1 10ms 20
|
||||
@@ -1,14 +1,15 @@
|
||||
# topo-6-node.txt
|
||||
# /------\ 0 /------\4
|
||||
|
||||
# /------\ /------\
|
||||
# | Src1 |<--+ +-->| Dst1 |
|
||||
# \------/ \ / \------/
|
||||
# \ 2 3 /
|
||||
# \ /
|
||||
# +-->/------\ "bottleneck" /------\<-+
|
||||
# | Rtr1 |<===============>| Rtr2 |
|
||||
# +-->\------/ \------/<-+
|
||||
# / \
|
||||
# /------\ / \ /------\5
|
||||
# | Src2 |<--+ 1 +-->| Dst2 |
|
||||
# /------\ / \ /------\
|
||||
# | Src2 |<--+ +-->| Dst2 |
|
||||
# \------/ \------/
|
||||
|
||||
router
|
||||
|
||||
@@ -281,6 +281,12 @@ StackHelper::PointToPointNetDeviceCallback(Ptr<Node> node, Ptr<L3Protocol> ndn,
|
||||
opts.allowFragmentation = true;
|
||||
opts.allowReassembly = true;
|
||||
opts.allowCongestionMarking = true;
|
||||
// Get DataRate
|
||||
DataRateValue dataRateAttribute;
|
||||
if (netDevice->GetAttributeFailSafe("DataRate", dataRateAttribute)) {
|
||||
auto dataRate = dataRateAttribute.Get();
|
||||
opts.C = dataRate.GetBitRate();
|
||||
}
|
||||
|
||||
auto linkService = make_unique<::nfd::face::GenericLinkService>(opts);
|
||||
|
||||
|
||||
@@ -265,14 +265,12 @@ extractLpLocalFields(NetPkt& netPacket, const lp::Packet& lpPacket)
|
||||
addTagFromField<lp::IncomingFaceIdTag, lp::IncomingFaceIdField>(netPacket, lpPacket);
|
||||
addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(netPacket, lpPacket);
|
||||
|
||||
// add by qjm
|
||||
addTagFromField<lp::DSZTag, lp::DSZField>(netPacket, lpPacket);
|
||||
|
||||
if (lpPacket.has<lp::HopCountTagField>()) {
|
||||
netPacket.setTag(make_shared<lp::HopCountTag>(lpPacket.get<lp::HopCountTagField>() + 1));
|
||||
}
|
||||
|
||||
addTagFromField<lp::PTag, lp::PTagField>(netPacket, lpPacket);
|
||||
addTagFromField<lp::PathidTag, lp::PathidTagField>(netPacket, lpPacket);
|
||||
addTagFromField<lp::RpTag, lp::RpTagField>(netPacket, lpPacket);
|
||||
addTagFromField<lp::RsTag, lp::RsTagField>(netPacket, lpPacket);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -97,13 +97,11 @@ public: // consumer
|
||||
lp::Packet lpPacket;
|
||||
addFieldFromTag<lp::NextHopFaceIdField, lp::NextHopFaceIdTag>(lpPacket, interest2);
|
||||
addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, interest2);
|
||||
|
||||
addFieldFromTag<lp::PTagField, lp::PTag>(lpPacket, interest2);
|
||||
addFieldFromTag<lp::PathidTagField, lp::PathidTag>(lpPacket, interest2);
|
||||
addFieldFromTag<lp::RpTagField, lp::RpTag>(lpPacket, interest2);
|
||||
addFieldFromTag<lp::RsTagField, lp::RsTag>(lpPacket, interest2);
|
||||
|
||||
|
||||
|
||||
// add by qjm
|
||||
addFieldFromTag<lp::DSZField, lp::DSZTag>(lpPacket, interest2);
|
||||
addFieldFromTag<lp::TosField, lp::TosTag>(lpPacket, interest2);
|
||||
|
||||
entry.recordForwarding();
|
||||
m_face.m_transport->send(finishEncoding(std::move(lpPacket), interest2.wireEncode(),
|
||||
'I', interest2.getName()));
|
||||
@@ -235,12 +233,7 @@ public: // producer
|
||||
lp::Packet lpPacket;
|
||||
addFieldFromTag<lp::CachePolicyField, lp::CachePolicyTag>(lpPacket, data);
|
||||
addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, data);
|
||||
|
||||
addFieldFromTag<lp::PTagField, lp::PTag>(lpPacket, data);
|
||||
addFieldFromTag<lp::RpTagField, lp::RpTag>(lpPacket, data);
|
||||
addFieldFromTag<lp::RsTagField, lp::RsTag>(lpPacket, data);
|
||||
addFieldFromTag<lp::PathidTagField, lp::PathidTag>(lpPacket, data);
|
||||
|
||||
|
||||
m_face.m_transport->send(finishEncoding(std::move(lpPacket), data.wireEncode(),
|
||||
'D', data.getName()));
|
||||
}
|
||||
|
||||
@@ -138,28 +138,20 @@ typedef FieldDecl<field_location_tags::Fragment,
|
||||
tlv::Fragment> FragmentField;
|
||||
BOOST_CONCEPT_ASSERT((Field<FragmentField>));
|
||||
|
||||
/**
|
||||
* DSZ Field
|
||||
* Data Size field
|
||||
*/
|
||||
typedef FieldDecl<field_location_tags::Header,
|
||||
uint64_t,
|
||||
tlv::PTag> PTagField;
|
||||
BOOST_CONCEPT_ASSERT((Field<PTagField>));
|
||||
uint64_t, tlv::DSZ> DSZField;
|
||||
|
||||
/**
|
||||
* Tos Field
|
||||
*/
|
||||
typedef FieldDecl<field_location_tags::Header,
|
||||
uint64_t,
|
||||
tlv::PathidTag> PathidTagField;
|
||||
BOOST_CONCEPT_ASSERT((Field<PathidTagField>));
|
||||
|
||||
typedef FieldDecl<field_location_tags::Header,
|
||||
uint64_t,
|
||||
tlv::RpTag> RpTagField;
|
||||
BOOST_CONCEPT_ASSERT((Field<RpTagField>));
|
||||
|
||||
typedef FieldDecl<field_location_tags::Header,
|
||||
uint64_t,
|
||||
tlv::RsTag> RsTagField;
|
||||
BOOST_CONCEPT_ASSERT((Field<RsTagField>));
|
||||
|
||||
|
||||
uint64_t, tlv::Tos> TosField;
|
||||
|
||||
|
||||
|
||||
/** \brief Set of all field declarations.
|
||||
*/
|
||||
@@ -180,10 +172,8 @@ typedef boost::mpl::set<
|
||||
PrefixAnnouncementField,
|
||||
HopCountTagField,
|
||||
GeoTagField,
|
||||
RsTagField,
|
||||
RpTagField,
|
||||
PathidTagField,
|
||||
PTagField
|
||||
DSZField,
|
||||
TosField
|
||||
> FieldSet;
|
||||
|
||||
} // namespace lp
|
||||
|
||||
@@ -80,13 +80,16 @@ typedef SimpleTag<PrefixAnnouncementHeader, 15> PrefixAnnouncementTag;
|
||||
*/
|
||||
typedef SimpleTag<uint64_t, 0x60000000> HopCountTag;
|
||||
|
||||
typedef SimpleTag<uint64_t, 16> PTag;
|
||||
/**
|
||||
* DSZ
|
||||
* Data Size
|
||||
*/
|
||||
typedef SimpleTag<uint64_t, 16> DSZTag;
|
||||
|
||||
typedef SimpleTag<uint64_t, 17> PathidTag;
|
||||
|
||||
typedef SimpleTag<uint64_t, 18> RpTag;
|
||||
|
||||
typedef SimpleTag<uint64_t, 19> RsTag;
|
||||
/**
|
||||
* Tos
|
||||
*/
|
||||
typedef SimpleTag<uint64_t, 17> TosTag;
|
||||
|
||||
/** \class GeoTag
|
||||
* \brief a packet tag for GeoTag field
|
||||
|
||||
@@ -50,10 +50,11 @@ enum {
|
||||
TxSequence = 840,
|
||||
NonDiscovery = 844,
|
||||
PrefixAnnouncement = 848,
|
||||
PTag = 852,
|
||||
PathidTag = 856,
|
||||
RpTag = 890,
|
||||
RsTag = 894
|
||||
|
||||
// Add DSZ Tag
|
||||
DSZ = 852,
|
||||
// Add Tos Tag
|
||||
Tos = 856
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
+4523
-4575
File diff suppressed because it is too large.
Load diff
@@ -69,7 +69,7 @@ main(int argc, char* argv[])
|
||||
|
||||
Simulator::Stop(Seconds(20.0));
|
||||
|
||||
ndn::L3RateTracer::InstallAll("rate-trace.txt", Seconds(0.5));
|
||||
ndn::L3RateTracer::InstallAll("rate-trace.txt", Seconds(0.1));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/ndnSIM-module.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
int
|
||||
@@ -34,13 +34,15 @@ main(int argc, char* argv[])
|
||||
Ptr<Node> producer1 = Names::Find<Node>("Dst1");
|
||||
Ptr<Node> producer2 = Names::Find<Node>("Dst2");
|
||||
|
||||
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerMIRCC");
|
||||
//consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second
|
||||
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerNWFQ");
|
||||
ndn::AppHelper consumerHelper2("ns3::ndn::ConsumerCbr");
|
||||
consumerHelper2.SetAttribute("Frequency", StringValue("500")); // 100 interests a second
|
||||
|
||||
|
||||
// on the first consumer node install a Consumer application
|
||||
// that will express interests in /dst1 namespace
|
||||
consumerHelper.SetPrefix("/dst1");
|
||||
consumerHelper.Install(consumer1);
|
||||
consumerHelper2.SetPrefix("/dst1");
|
||||
consumerHelper2.Install(consumer1);
|
||||
|
||||
// on the second consumer node install a Consumer application
|
||||
// that will express interests in /dst2 namespace
|
||||
@@ -76,9 +78,9 @@ main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
return ns3::main(argc, argv);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user