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
@@ -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,6 +192,16 @@ 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);
|
||||
@@ -411,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);
|
||||
}
|
||||
|
||||
@@ -456,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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,6 +265,9 @@ 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));
|
||||
}
|
||||
|
||||
@@ -98,6 +98,10 @@ public: // consumer
|
||||
addFieldFromTag<lp::NextHopFaceIdField, lp::NextHopFaceIdTag>(lpPacket, interest2);
|
||||
addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(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()));
|
||||
|
||||
@@ -138,6 +138,21 @@ 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::DSZ> DSZField;
|
||||
|
||||
/**
|
||||
* Tos Field
|
||||
*/
|
||||
typedef FieldDecl<field_location_tags::Header,
|
||||
uint64_t, tlv::Tos> TosField;
|
||||
|
||||
|
||||
|
||||
/** \brief Set of all field declarations.
|
||||
*/
|
||||
typedef boost::mpl::set<
|
||||
@@ -156,7 +171,9 @@ typedef boost::mpl::set<
|
||||
NonDiscoveryField,
|
||||
PrefixAnnouncementField,
|
||||
HopCountTagField,
|
||||
GeoTagField
|
||||
GeoTagField,
|
||||
DSZField,
|
||||
TosField
|
||||
> FieldSet;
|
||||
|
||||
} // namespace lp
|
||||
|
||||
@@ -80,6 +80,17 @@ typedef SimpleTag<PrefixAnnouncementHeader, 15> PrefixAnnouncementTag;
|
||||
*/
|
||||
typedef SimpleTag<uint64_t, 0x60000000> HopCountTag;
|
||||
|
||||
/**
|
||||
* DSZ
|
||||
* Data Size
|
||||
*/
|
||||
typedef SimpleTag<uint64_t, 16> DSZTag;
|
||||
|
||||
/**
|
||||
* Tos
|
||||
*/
|
||||
typedef SimpleTag<uint64_t, 17> TosTag;
|
||||
|
||||
/** \class GeoTag
|
||||
* \brief a packet tag for GeoTag field
|
||||
*
|
||||
|
||||
@@ -50,6 +50,11 @@ enum {
|
||||
TxSequence = 840,
|
||||
NonDiscovery = 844,
|
||||
PrefixAnnouncement = 848,
|
||||
|
||||
// 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();
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
#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::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
|
||||
consumerHelper2.SetPrefix("/dst1");
|
||||
consumerHelper2.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);
|
||||
}
|
||||
Reference in new issue
Block a user