wella_salwa
Messages postés33Date d'inscriptionlundi 31 octobre 2022StatutMembreDernière intervention11 décembre 2024
-
Modifié le 11 avril 2023 à 16:49
mamiemando
Messages postés33446Date d'inscriptionjeudi 12 mai 2005StatutModérateurDernière intervention20 décembre 2024
-
12 avril 2023 à 13:32
Bonjour,
J'essaie d'afficher les deux variables ''m-highdata'' et ''m_window'' de la classe ConsumerPcon dans ndnSIM
J'ai utilisé la topologie jointe (ndn-congestion-topo-plugin.cpp), pour obtenir un affichage dans le fichier '' outputFile.txt".
Le problème rencontré est que ndnSIM ne les affiche que pour le premier temps de simulation (time=0 / m_highdata =0 / m_window =0)
Comment puis-je procéder pour obtenir toutes les valeurs durant toute la période de simulation ?
ndn-consumer-pcon.cpp
#include "ndn-consumer-pcon.hpp"
#include <iostream>
#include <fstream>
using namespace std;
NS_LOG_COMPONENT_DEFINE("ndn.ConsumerPcon");
namespace ns3 {
namespace ndn {
NS_OBJECT_ENSURE_REGISTERED(ConsumerPcon);
constexpr double ConsumerPcon::CUBIC_C;
constexpr uint32_t ConsumerPcon::BIC_MAX_INCREMENT;
constexpr uint32_t ConsumerPcon::BIC_LOW_WINDOW;
ConsumerPcon consumer ;
TypeId
ConsumerPcon::GetTypeId()
{
static TypeId tid =
TypeId("ns3::ndn::ConsumerPcon")
.SetGroupName("Ndn")
.SetParent<ConsumerWindow>()
.AddConstructor<ConsumerPcon>()
.AddAttribute("CcAlgorithm",
"Specify which window adaptation algorithm to use (AIMD, BIC, or CUBIC)",
EnumValue(CcAlgorithm::AIMD),
MakeEnumAccessor(&ConsumerPcon::m_ccAlgorithm),
MakeEnumChecker(CcAlgorithm::AIMD, "AIMD", CcAlgorithm::BIC, "BIC",
CcAlgorithm::CUBIC, "CUBIC"))
.AddAttribute("Beta",
"TCP Multiplicative Decrease factor",
DoubleValue(0.5),
MakeDoubleAccessor(&ConsumerPcon::m_beta),
MakeDoubleChecker<double>())
.AddAttribute("CubicBeta",
"TCP CUBIC Multiplicative Decrease factor",
DoubleValue(0.8),
MakeDoubleAccessor(&ConsumerPcon::m_cubicBeta),
MakeDoubleChecker<double>())
.AddAttribute("AddRttSuppress",
"Minimum number of RTTs (1 + this factor) between window decreases",
DoubleValue(0.5), // This default value was chosen after manual testing
MakeDoubleAccessor(&ConsumerPcon::m_addRttSuppress),
MakeDoubleChecker<double>())
.AddAttribute("ReactToCongestionMarks",
"If true, process received congestion marks",
BooleanValue(true),
MakeBooleanAccessor(&ConsumerPcon::m_reactToCongestionMarks),
MakeBooleanChecker())
.AddAttribute("UseCwa",
"If true, use Conservative Window Adaptation",
BooleanValue(true),
MakeBooleanAccessor(&ConsumerPcon::m_useCwa),
MakeBooleanChecker())
.AddAttribute("UseCubicFastConvergence",
"If true, use TCP CUBIC Fast Convergence",
BooleanValue(false),
MakeBooleanAccessor(&ConsumerPcon::m_useCubicFastConv),
MakeBooleanChecker());
return tid;
}
ConsumerPcon::ConsumerPcon()
: m_ssthresh(std::numeric_limits<double>::max())
, m_highData(0)
, m_recPoint(0.0)
, m_cubicWmax(0)
, m_cubicLastWmax(0)
, m_cubicLastDecrease(time::steady_clock::now())
, m_bicMinWin(0)
, m_bicMaxWin(std::numeric_limits<double>::max())
, m_bicTargetWin(0)
, m_bicSsCwnd(0)
, m_bicSsTarget(0)
, m_isBicSs(false)
{
}
void
ConsumerPcon::OnData(shared_ptr<const Data> data)
{
Consumer::OnData(data);
uint64_t sequenceNum = data->getName().get(-1).toSequenceNumber();
// Set highest received Data to sequence number
if (m_highData < sequenceNum) {
m_highData = sequenceNum;
}
if (data->getCongestionMark() > 0) {
if (m_reactToCongestionMarks) {
NS_LOG_DEBUG("Received congestion mark: " << data->getCongestionMark());
WindowDecrease();
}
else {
NS_LOG_DEBUG("Ignored received congestion mark: " << data->getCongestionMark());
}
}
else {
WindowIncrease();
}
if (m_inFlight > static_cast<uint32_t>(0)) {
m_inFlight--;
}
NS_LOG_DEBUG("Window: " << m_window << ", InFlight: " << m_inFlight);
ScheduleNextPacket();
}
void
ConsumerPcon::OnTimeout(uint32_t sequenceNum)
{
WindowDecrease();
if (m_inFlight > static_cast<uint32_t>(0)) {
m_inFlight--;
}
NS_LOG_DEBUG("Window: " << m_window << ", InFlight: " << m_inFlight);
Consumer::OnTimeout(sequenceNum);
}
void
ConsumerPcon::WindowIncrease()
{
if (m_ccAlgorithm == CcAlgorithm::AIMD) {
if (m_window < m_ssthresh) {
m_window += 1.0;
}
else {
m_window += (1.0 / m_window);
}
}
else if (m_ccAlgorithm == CcAlgorithm::CUBIC) {
CubicIncrease();
}
else if (m_ccAlgorithm == CcAlgorithm::BIC) {
BicIncrease();
}
else {
BOOST_ASSERT_MSG(false, "Unknown CC Algorithm");
}
NS_LOG_DEBUG("Window size increased to " << m_window);
}
void
ConsumerPcon::WindowDecrease()
{
if (!m_useCwa || m_highData > m_recPoint) {
const double diff = m_seq - m_highData;
BOOST_ASSERT(diff > 0);
m_recPoint = m_seq + (m_addRttSuppress * diff);
if (m_ccAlgorithm == CcAlgorithm::AIMD) {
// Normal TCP Decrease:
m_ssthresh = m_window * m_beta;
m_window = m_ssthresh;
}
else if (m_ccAlgorithm == CcAlgorithm::CUBIC) {
CubicDecrease();
}
else if (m_ccAlgorithm == CcAlgorithm::BIC) {
BicDecrease();
}
else {
BOOST_ASSERT_MSG(false, "Unknown CC Algorithm");
}
// Window size cannot be reduced below initial size
if (m_window < m_initialWindow) {
m_window = m_initialWindow;
}
NS_LOG_DEBUG("Window size decreased to " << m_window);
}
else {
NS_LOG_DEBUG("Window decrease suppressed, HighData: " << m_highData << ", RecPoint: " << m_recPoint);
}
}
void
ConsumerPcon::BicIncrease()
{
if (m_window < BIC_LOW_WINDOW) {
// Normal TCP AIMD behavior
if (m_window < m_ssthresh) {
m_window = m_window + 1;
}
else {
m_window = m_window + 1.0 / m_window;
}
}
else if (!m_isBicSs) {
// Binary increase
if (m_bicTargetWin - m_window < BIC_MAX_INCREMENT) { // Binary search
m_window += (m_bicTargetWin - m_window) / m_window;
}
else {
m_window += BIC_MAX_INCREMENT / m_window; // Additive increase
}
// FIX for equal double values.
if (m_window + 0.00001 < m_bicMaxWin) {
m_bicMinWin = m_window;
m_bicTargetWin = (m_bicMaxWin + m_bicMinWin) / 2;
}
else {
m_isBicSs = true;
m_bicSsCwnd = 1;
m_bicSsTarget = m_window + 1.0;
m_bicMaxWin = std::numeric_limits<double>::max();
}
}
else {
// BIC slow start
m_window += m_bicSsCwnd / m_window;
if (m_window >= m_bicSsTarget) {
m_bicSsCwnd = 2 * m_bicSsCwnd;
m_bicSsTarget = m_window + m_bicSsCwnd;
}
if (m_bicSsCwnd >= BIC_MAX_INCREMENT) {
m_isBicSs = false;
}
}
}
void
ConsumerPcon::BicDecrease()
{
// BIC Decrease
if (m_window >= BIC_LOW_WINDOW) {
auto prev_max = m_bicMaxWin;
m_bicMaxWin = m_window;
m_window = m_window * m_cubicBeta;
m_bicMinWin = m_window;
if (prev_max > m_bicMaxWin) {
// Fast Convergence
m_bicMaxWin = (m_bicMaxWin + m_bicMinWin) / 2;
}
m_bicTargetWin = (m_bicMaxWin + m_bicMinWin) / 2;
}
else {
// Normal TCP Decrease:
m_ssthresh = m_window * m_cubicBeta;
m_window = m_ssthresh;
}
}
void
ConsumerPcon::CubicIncrease()
{
// 1. Time since last congestion event in Seconds
const double t = time::duration_cast<time::microseconds>(
time::steady_clock::now() - m_cubicLastDecrease).count() / 1e6;
// 2. Time it takes to increase the window to cubic_wmax
// K = cubic_root(W_max*(1-beta_cubic)/C) (Eq. 2)
const double k = std::cbrt(m_cubicWmax * (1 - m_cubicBeta) / CUBIC_C);
// 3. Target: W_cubic(t) = C*(t-K)^3 + W_max (Eq. 1)
const double w_cubic = CUBIC_C * std::pow(t - k, 3) + m_cubicWmax;
// 4. Estimate of Reno Increase (Currently Disabled)
// const double rtt = m_rtt->GetCurrentEstimate().GetSeconds();
// const double w_est = m_cubic_wmax*m_beta + (3*(1-m_beta)/(1+m_beta)) * (t/rtt);
constexpr double w_est = 0.0;
// Actual adaptation
if (m_window < m_ssthresh) {
m_window += 1.0;
}
else {
BOOST_ASSERT(m_cubicWmax > 0);
double cubic_increment = std::max(w_cubic, w_est) - m_window;
// Cubic increment must be positive:
// Note: This change is not part of the RFC, but I added it to improve performance.
if (cubic_increment < 0) {
cubic_increment = 0.0;
}
m_window += cubic_increment / m_window;
}
}
void
ConsumerPcon::CubicDecrease()
{
// This implementation is ported from https://datatracker.ietf.org/doc/rfc8312/
const double FAST_CONV_DIFF = 1.0; // In percent
// A flow remembers the last value of W_max,
// before it updates W_max for the current congestion event.
// Current w_max < last_wmax
if (m_useCubicFastConv && m_window < m_cubicLastWmax * (1 - FAST_CONV_DIFF / 100)) {
m_cubicLastWmax = m_window;
m_cubicWmax = m_window * (1.0 + m_cubicBeta) / 2.0;
}
else {
// Save old cwnd as w_max:
m_cubicLastWmax = m_window;
m_cubicWmax = m_window;
}
m_ssthresh = m_window * m_cubicBeta;
m_ssthresh = std::max<double>(m_ssthresh, m_initialWindow);
m_window = m_ssthresh;
m_cubicLastDecrease = time::steady_clock::now();
}
} // namespace ndn
} // namespace ns3
ndn-congestion-topo-plugin.cpp
#include "ns3/ndnSIM/apps/ndn-consumer-pcon.hpp"
#include "ns3/ndnSIM/apps/ndn-consumer-window.hpp"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/ndnSIM-module.h"
#include <iostream>
#include <fstream>
namespace ns3 {
int main(int argc, char* argv[] ) {
ns3::ndn::ConsumerPcon consumer ;
CommandLine cmd;
cmd.Parse(argc, argv);
AnnotatedTopologyReader topologyReader("", 25);
topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-6-node.txt");
topologyReader.Read();
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.setPolicy("nfd::cs::lru");
ndnHelper.setCsSize(0);
ndnHelper.InstallAll();
// Choosing forwarding strategy
ndn::StrategyChoiceHelper::InstallAll("/prefix", "/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::ConsumerCbr");
consumerHelper.SetAttribute("Frequency", StringValue("90")); // 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.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(40.0));
std::string file = "outputFile.txt";
std::ofstream out;
out.open(file, std::fstream::app); // if you want to truncate the file instead of appending to it use "trunc" instead of "app"
auto *coutbuf = std::cout.rdbuf();
std::cout.rdbuf(out.rdbuf());
std::cout << " The value of m_highData " << consumer.m_highData << std::endl;
std::cout << " The value of m_window " << consumer.m_window << std::endl;
/* reset cout buffer **/
std::cout.rdbuf(coutbuf);
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
wella_salwa
Messages postés33Date d'inscriptionlundi 31 octobre 2022StatutMembreDernière intervention11 décembre 2024 12 avril 2023 à 12:02
Bonjour mamiemando ,
c'est à propos la transmission IP-V6 et pas NDN
Merci
mamiemando
Messages postés33446Date d'inscriptionjeudi 12 mai 2005StatutModérateurDernière intervention20 décembre 20247 812
>
wella_salwa
Messages postés33Date d'inscriptionlundi 31 octobre 2022StatutMembreDernière intervention11 décembre 2024 12 avril 2023 à 13:32
L'important ce n'est pas l'exemple, c'est le concept présenté dans le tutoriel (notamment celui de probe). Certes, la documentation illustre cette notion avec une simulation mettant en jeu IPv6, mais le principe reste le même dans NDN. La partie importante, c'est celle avec les lignes de code ajoutée en vert (celle qui commencent par un +) qu'il faut compléter et adapter à ton cas d'usage.
std::string probeType;
std::string tracePath;
if (useV6 == false)
{
...
probeType = "ns3::Ipv4PacketProbe";
tracePath = "/NodeList/*/$ns3::Ipv4L3Protocol/Tx";
}
else
{
...
probeType = "ns3::Ipv6PacketProbe";
tracePath = "/NodeList/*/$ns3::Ipv6L3Protocol/Tx";
}
...
// Use GnuplotHelper to plot the packet byte count over time
GnuplotHelper plotHelper;
// Configure the plot. The first argument is the file name prefix
// for the output files generated. The second, third, and fourth
// arguments are, respectively, the plot title, x-axis, and y-axis labels
plotHelper.ConfigurePlot("seventh-packet-byte-count",
"Packet Byte Count vs. Time",
"Time(Seconds)",
"Packet Byte Count");
// Specify the probe type, trace source path (in configuration namespace), and
// probe output trace source ("OutputBytes") to plot. The fourth argument
// specifies the name of the data series label on the plot. The last
// argument formats the plot by specifying where the key should be placed.
plotHelper.PlotProbe(probeType,
tracePath,
"OutputBytes",
"Packet Byte Count",
GnuplotAggregator::KEY_BELOW);
// Use FileHelper to write out the packet byte count over time
FileHelper fileHelper;
// Configure the file to be written, and the formatting of output data.
fileHelper.ConfigureFile("seventh-packet-byte-count",
FileAggregator::FORMATTED);
// Set the labels for this formatted output file.
fileHelper.Set2dFormat("Time (Seconds) = %.3e\tPacket Byte Count = %.0f");
// Specify the probe type, probe path (in configuration namespace), and
// probe output trace source ("OutputBytes") to write.
fileHelper.WriteProbe(probeType,
tracePath,
"OutputBytes");
12 avril 2023 à 12:02
Bonjour mamiemando ,
c'est à propos la transmission IP-V6 et pas NDN
Merci
12 avril 2023 à 13:32
L'important ce n'est pas l'exemple, c'est le concept présenté dans le tutoriel (notamment celui de probe). Certes, la documentation illustre cette notion avec une simulation mettant en jeu IPv6, mais le principe reste le même dans NDN. La partie importante, c'est celle avec les lignes de code ajoutée en vert (celle qui commencent par un +) qu'il faut compléter et adapter à ton cas d'usage.