From f6bdac05db7f4def3d60332b2db0544abaed4bcb Mon Sep 17 00:00:00 2001 From: charliebarber Date: Mon, 4 Mar 2024 16:36:16 +0000 Subject: [PATCH 01/28] Congestion simulation with sockets, not clear if tracing correctly. Need to verify. --- src/basic_congestion.cc | 411 ++++++++++++++++++++++++++++++++++ src/simple_dumbbell_topo.cc | 434 ++++++++++++++++++++---------------- 2 files changed, 649 insertions(+), 196 deletions(-) create mode 100644 src/basic_congestion.cc diff --git a/src/basic_congestion.cc b/src/basic_congestion.cc new file mode 100644 index 00000000..480b6e00 --- /dev/null +++ b/src/basic_congestion.cc @@ -0,0 +1,411 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "ns3/applications-module.h" +#include "ns3/core-module.h" +#include "ns3/internet-module.h" +#include "ns3/network-module.h" +#include "ns3/point-to-point-module.h" +#include "ns3/traffic-control-module.h" + +#include "../libs/random/random.hpp" + +using namespace ns3; +using Random = effolkronium::random_static; + +// ---------------------------------------------------- // +// --- BEGIN OF SIMULATION CONFIGURATION PARAMETERS --- // +// ---------------------------------------------------- // + +// Random Seed +uint32_t seed = 1; + +// ---[TRACES]--- +// Store Traces +bool storeTraces = true; + +// Location to store traces +std::string tracesPath = "traces/"; + +// ---[SIMULATION PARAMETERS]--- +// Time to initiate the TCP connection +Time startTimeTCP = Seconds(0.1); + +// Time to stop the TCP connection +Time stopTimeTCP = Seconds(5); + +// Simulation stop time +Time stopTimeSimulation = Seconds(5000); + +// TCP flow interval +Time intervalTCP = Seconds(1); + +// ---[TCP PARAMETERS] --- +uint32_t segmentSize = 1024; +uint32_t MTU_bytes = segmentSize + 54; +uint8_t delAckCount = 1; +uint8_t initialCwnd = 1; +// std::string delAckTimeout = "200ms"; +std::string delAckTimeout = "1ms"; +std::string socketFactory = "ns3::TcpSocketFactory"; +std::string qdiscTypeId = "ns3::PFifoFastQueueDisc"; +std::string tcpRecovery = "ns3::TcpClassicRecovery"; +// std::string tcpVariantId = "ns3::TcpCubic"; +std::string tcpVariantId = "ns3::TcpLinuxReno"; +bool enableSack = false; +double minRTO = 1.0; + +// ---[TOPOLOGY PARAMETERS]--- +std::string bandwidth_bottleneck = "1Mbps"; +std::string bandwidth_access = "20Mbps"; +std::string delay_access = "15ms"; +std::string delay_bottleneck = "20ms"; +std::string delay_serialization = "1.9ms"; + +// ---[POINTER TO THE DEVICE THAT WILL IMPLEMENT PACKET DROPING] +NetDeviceContainer *netDeviceToDropPacket = NULL; + +// -------------------------------------------------- // +// --- END OF SIMULATION CONFIGURATION PARAMETERS --- // +// -------------------------------------------------- // + +// Global Variables +Ptr sinker; + +int packetsDroppedInQueue = 0; +int64_t lastTotalRx = 0; +uint32_t bytes_to_send = 10000; + +uint32_t cnt_packets = 0; + +void TraceCwnd(uint32_t node, uint32_t cwndWindow, + Callback CwndTrace) { + Config::ConnectWithoutContext( + "/NodeList/" + std::to_string(node) + "/$ns3::TcpL4Protocol/SocketList/" + + std::to_string(cwndWindow) + "/CongestionWindow", + CwndTrace); +} + +static void CwndChange(uint32_t oldCwnd, uint32_t newCwnd) { + std::ofstream fPlotQueue(tracesPath + "cwnd.txt", + std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now().GetSeconds() << " " << newCwnd / segmentSize + << " " << newCwnd << std::endl; + fPlotQueue.close(); +} + +void InstallBulkSend(Ptr node, Ipv4Address address, uint16_t port, + std::string socketFactory, uint32_t nodeId, + uint32_t cwndWindow, + Callback CwndTrace, + uint32_t maxBytesToSend, Time startTime) { + BulkSendHelper source(socketFactory, InetSocketAddress(address, port)); + source.SetAttribute("MaxBytes", UintegerValue(maxBytesToSend)); + ApplicationContainer sourceApps = source.Install(node); + sourceApps.Start(startTime); + sourceApps.Stop(stopTimeTCP); + if (storeTraces == false) { + Simulator::Schedule(startTime + Seconds(0.001), &TraceCwnd, nodeId, + cwndWindow, CwndTrace); + } +} + +void InstallPacketSink(Ptr node, uint16_t port, std::string socketFactory, + Time startTime, Time stopTime) { + PacketSinkHelper sink(socketFactory, + InetSocketAddress(Ipv4Address::GetAny(), port)); + ApplicationContainer sinkApps = sink.Install(node); + sinker = StaticCast(sinkApps.Get(0)); + sinkApps.Start(startTime); + sinkApps.Stop(stopTime); +} + +static void DropAtQueue(Ptr stream, + Ptr item) { + *stream->GetStream() << Simulator::Now().GetSeconds() << " 1" << std::endl; + packetsDroppedInQueue++; +} + +void PacketsInQueueDisc(uint32_t oldValue, uint32_t newValue) { + std::ofstream fPlotQueue( + std::stringstream(tracesPath + "pktsQueueDisc.txt").str().c_str(), + std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; + fPlotQueue.close(); +} + +void PacketsInDroptail(uint32_t oldValue, uint32_t newValue) { + std::ofstream fPlotQueue( + std::stringstream(tracesPath + "pktsDropTail.txt").str().c_str(), + std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; + fPlotQueue.close(); +} + +void ExaminePacket(Ptr packet) { + // Extract TCP Header from the packet + TcpHeader tcpHeader; + packet->PeekHeader(tcpHeader); + uint32_t payloadSize = packet->GetSize(); + + // Extract the SEQ and ACK numbers + uint32_t seq = tcpHeader.GetSequenceNumber().GetValue(); + uint32_t ack = tcpHeader.GetAckNumber().GetValue(); + + std::cout << "[TCP PACKET] [SEQ: " << seq << "] [ACK: " << ack + << "] [Payload Length: " << payloadSize + << "] PacketUid: " << packet->GetUid() << std::endl; +} + +// void SimulateCongestion(Ptr congestionNode, Time startDelay, +// Time duration, unsigned int numPackets, +// unsigned int packetSize, Time interval, +// Ipv4Address receiverAddress, uint16_t port) { +// BulkSendHelper source("ns3::UdpSocketFactory", +// InetSocketAddress(receiverAddress, port)); +// +// // Set bulk sender attributes +// source.SetAttribute("MaxBytes", UintegerValue(numPackets * packetSize)); +// source.SetAttribute("SendSize", UintegerValue(packetSize)); +// // source.SetAttribute("interval", TimeValue(interval)); +// +// // Install application on congestionNode +// ApplicationContainer apps = source.Install(congestionNode); +// // And start it after specified delay +// apps.Start(startDelay); +// apps.Stop(startDelay + duration); +// } + +void SimulateCongestion(Ptr congestionNode, Time startDelay, + Time duration, unsigned int numPackets, + unsigned int packetSize, Time interval, + Ipv4Address receiverAddress, uint16_t port) { + // Create a UDP socket + Ptr socket = + Socket::CreateSocket(congestionNode, UdpSocketFactory::GetTypeId()); + InetSocketAddress receiverSocketAddress(receiverAddress, port); + + // Schedule sending packets using the UDP socket + Simulator::Schedule(startDelay, [socket, receiverSocketAddress, numPackets, + packetSize, interval]() { + for (unsigned int i = 0; i < numPackets; ++i) { + // std::cout << "sending packet " << i << std::endl; + Ptr packet = Create(packetSize); + int err = socket->SendTo(packet, packetSize, receiverSocketAddress); + if (err == -1) { + std::cout << "error sending packet " << i << std::endl; + } + } + }); + + // Stop sending packets after the specified duration + Simulator::Schedule(startDelay + duration, &Socket::Close, socket); +} + +int main(int argc, char *argv[]) { + // Command line arguments + CommandLine cmd; + cmd.AddValue("tcpVariantId", "TCP variant", tcpVariantId); + cmd.AddValue("enableSack", "Enable/disable sack in TCP", enableSack); + cmd.AddValue("seed", "The random seed", seed); + cmd.AddValue("simStopTime", "The simulation stop time", stopTimeSimulation); + cmd.AddValue("intervalTCP", "The TCP interval", intervalTCP); + cmd.AddValue("initialCwnd", "Initial CWND window", initialCwnd); + cmd.AddValue("bytesToSend", "Number of bytes to send", bytes_to_send); + cmd.Parse(argc, argv); + + // Set Random Seed + Random::seed(seed); + + // TCP Recovery Algorithm + Config::SetDefault("ns3::TcpL4Protocol::RecoveryType", + TypeIdValue(TypeId::LookupByName(tcpRecovery))); + + // Set Congestion Control Algorithm + Config::SetDefault("ns3::TcpL4Protocol::SocketType", + StringValue(tcpVariantId)); + Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(1073741824)); + Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(1073741824)); + + // Set default initial congestion window + Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(initialCwnd)); + + // Set default delayed ack count to a specified value + Config::SetDefault("ns3::TcpSocket::DelAckTimeout", + TimeValue(Time(delAckTimeout))); + Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(delAckCount)); + // Config::SetDefault("ns3::TcpSocket::SetTcpNoDelay", BooleanValue(true)); + + // Set default segment size of TCP packet to a specified value + Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(segmentSize)); + + // Enable/Disable SACK in TCP + Config::SetDefault("ns3::TcpSocketBase::Sack", BooleanValue(enableSack)); + + Config::SetDefault("ns3::TcpSocketBase::MinRto", TimeValue(Seconds(minRTO))); + + NodeContainer leftNodes, rightNodes, routers; + routers.Create(2); + leftNodes.Create(1); + rightNodes.Create(1); + + Names::Add("Router1", routers.Get(0)); + Names::Add("Router2", routers.Get(1)); + Names::Add("Sender", leftNodes.Get(0)); + Names::Add("Receiver", rightNodes.Get(0)); + + // Congestion node setup + NodeContainer congestionNode; + congestionNode.Create(1); + Names::Add("CongestionSender", congestionNode.Get(0)); + + DataRate b_access(bandwidth_access); + DataRate b_bottleneck(bandwidth_bottleneck); + Time d_access(delay_access); + Time d_bottleneck(delay_bottleneck); + Time d_serialization(delay_serialization); + + uint32_t max_bottleneck_bytes = static_cast( + ((std::min(b_access, b_bottleneck).GetBitRate() / 8) * + (((d_access * 2) + d_bottleneck) * 2 + d_serialization).GetSeconds())); + uint32_t projected_queue_max_packets = + std::ceil(max_bottleneck_bytes / MTU_bytes); + + // Set Droptail queue size to 1 packet + Config::SetDefault("ns3::DropTailQueue::MaxSize", StringValue("1p")); + + // Create the point-to-point link helpers and connect two router nodes + PointToPointHelper pointToPointRouter; + pointToPointRouter.SetDeviceAttribute("DataRate", + StringValue(bandwidth_bottleneck)); + pointToPointRouter.SetChannelAttribute("Delay", + StringValue(delay_bottleneck)); + + NetDeviceContainer r1r2ND = + pointToPointRouter.Install(routers.Get(0), routers.Get(1)); + + // Create the point-to-point link helpers and connect leaf nodes to router + PointToPointHelper pointToPointLeaf; + pointToPointLeaf.SetDeviceAttribute("DataRate", + StringValue(bandwidth_access)); + pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); + + NetDeviceContainer leftToRouter = + pointToPointLeaf.Install(leftNodes.Get(0), routers.Get(0)); + NetDeviceContainer routerToRight = + pointToPointLeaf.Install(routers.Get(1), rightNodes.Get(0)); + + // Link CongestioNSender to Router1 + NetDeviceContainer congestionSenderToRouter = + pointToPointLeaf.Install(congestionNode.Get(0), routers.Get(0)); + + InternetStackHelper internetStack; + internetStack.Install(leftNodes); + internetStack.Install(rightNodes); + internetStack.Install(routers); + internetStack.Install(congestionNode); + + Ipv4AddressHelper ipAddresses("10.0.0.0", "255.255.255.0"); + Ipv4InterfaceContainer r1r2IPAddress = ipAddresses.Assign(r1r2ND); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer leftToRouterIPAddress = + ipAddresses.Assign(leftToRouter); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer routerToRightIPAddress = + ipAddresses.Assign(routerToRight); + ipAddresses.NewNetwork(); + + Ipv4GlobalRoutingHelper::PopulateRoutingTables(); + + // Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", + // QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, + // projected_queue_max_packets))); + Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", + QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, 1))); + + TrafficControlHelper tch; + tch.SetRootQueueDisc("ns3::PfifoFastQueueDisc"); + QueueDiscContainer qd; + tch.Uninstall(routers.Get(0)->GetDevice(0)); + qd.Add(tch.Install(routers.Get(0)->GetDevice(0)).Get(0)); + + /* Trace the QueueDisc Queue size */ + if (storeTraces == false) { + Ptr q = qd.Get(0); + q->TraceConnectWithoutContext("PacketsInQueue", + MakeCallback(&PacketsInQueueDisc)); + } + + /* Trace the DropTail Queue size */ + if (storeTraces) { + Ptr nd = routers.Get(0)->GetDevice(0); + Ptr ptpnd = DynamicCast(nd); + Ptr> queue = ptpnd->GetQueue(); + queue->TraceConnectWithoutContext("PacketsInQueue", + MakeCallback(&PacketsInDroptail)); + } + + /* Trace packets dropped by the QueueDisc Queue */ + if (storeTraces) { + AsciiTraceHelper ascii; + Ptr streamWrapper; + streamWrapper = ascii.CreateFileStream(tracesPath + "droppedQueueDisc.txt"); + qd.Get(0)->TraceConnectWithoutContext( + "Drop", MakeBoundCallback(&DropAtQueue, streamWrapper)); + } + + netDeviceToDropPacket = &r1r2ND; + /* Callback to the ExaminePacket */ + r1r2ND.Get(0)->TraceConnectWithoutContext("MacTx", + MakeCallback(&ExaminePacket)); + + /* Packet Printing is mandatory for the Packet Drop Test */ + Packet::EnablePrinting(); + + uint16_t server_port = 50000; + /* Install packet sink at receiver side */ + InstallPacketSink(rightNodes.Get(0), server_port, socketFactory, + Seconds(0.01), stopTimeSimulation); + + /* Install BulkSend application */ + InstallBulkSend(leftNodes.Get(0), routerToRightIPAddress.GetAddress(1), + server_port, socketFactory, 2, 0, MakeCallback(&CwndChange), + bytes_to_send, Seconds(0.2)); + + // Congestion PARAMETERS + uint16_t serverPort = 50000; + Time startDelay = Seconds(1.0); + Time duration = Seconds(5.0); + uint32_t numPackets = 512; + uint32_t packetSize = 1024; + Time interval = MilliSeconds(10); + Ipv4Address receiverAddress = routerToRightIPAddress.GetAddress(1); + + // Schedule the congestion + // Simulator::Schedule(startDelay, [congestionNode, startDelay, duration, + // numPackets, packetSize, interval, + // receiverAddress, serverPort]() { + // Ptr node = congestionNode.Get(0); + // // double startDelaySeconds = startDelay.GetSeconds(); + // // double duration + // SimulateCongestion(node, startDelay, duration, numPackets, packetSize, + // interval, receiverAddress, serverPort); + // }); + + SimulateCongestion(congestionNode.Get(0), startDelay, duration, numPackets, + packetSize, interval, receiverAddress, serverPort); + + if (storeTraces) { + pointToPointLeaf.EnablePcapAll(tracesPath); + } + + Simulator::Stop(stopTimeSimulation); + Simulator::Run(); + Simulator::Destroy(); + return 0; +} diff --git a/src/simple_dumbbell_topo.cc b/src/simple_dumbbell_topo.cc index 3c293a99..11631036 100644 --- a/src/simple_dumbbell_topo.cc +++ b/src/simple_dumbbell_topo.cc @@ -1,16 +1,16 @@ +#include +#include +#include +#include #include #include -#include #include -#include -#include -#include +#include "ns3/applications-module.h" #include "ns3/core-module.h" -#include "ns3/network-module.h" #include "ns3/internet-module.h" +#include "ns3/network-module.h" #include "ns3/point-to-point-module.h" -#include "ns3/applications-module.h" #include "ns3/traffic-control-module.h" #include "../libs/random/random.hpp" @@ -50,26 +50,25 @@ uint32_t segmentSize = 1024; uint32_t MTU_bytes = segmentSize + 54; uint8_t delAckCount = 1; uint8_t initialCwnd = 1; -//std::string delAckTimeout = "200ms"; +// std::string delAckTimeout = "200ms"; std::string delAckTimeout = "1ms"; std::string socketFactory = "ns3::TcpSocketFactory"; std::string qdiscTypeId = "ns3::PFifoFastQueueDisc"; std::string tcpRecovery = "ns3::TcpClassicRecovery"; -//std::string tcpVariantId = "ns3::TcpCubic"; +// std::string tcpVariantId = "ns3::TcpCubic"; std::string tcpVariantId = "ns3::TcpLinuxReno"; bool enableSack = false; double minRTO = 1.0; // ---[TOPOLOGY PARAMETERS]--- -std::string bandwidth_bottleneck = "10Mbps"; +std::string bandwidth_bottleneck = "1Mbps"; std::string bandwidth_access = "20Mbps"; std::string delay_access = "15ms"; std::string delay_bottleneck = "20ms"; std::string delay_serialization = "1.9ms"; // ---[POINTER TO THE DEVICE THAT WILL IMPLEMENT PACKET DROPING] -NetDeviceContainer * netDeviceToDropPacket = NULL; - +NetDeviceContainer *netDeviceToDropPacket = NULL; // -------------------------------------------------- // // --- END OF SIMULATION CONFIGURATION PARAMETERS --- // @@ -84,208 +83,251 @@ uint32_t bytes_to_send = 1000; uint32_t cnt_packets = 0; -void TraceCwnd(uint32_t node, uint32_t cwndWindow, Callback CwndTrace){ - Config::ConnectWithoutContext("/NodeList/" + std::to_string(node) + "/$ns3::TcpL4Protocol/SocketList/" + std::to_string(cwndWindow) + "/CongestionWindow", CwndTrace); +void TraceCwnd(uint32_t node, uint32_t cwndWindow, + Callback CwndTrace) { + Config::ConnectWithoutContext( + "/NodeList/" + std::to_string(node) + "/$ns3::TcpL4Protocol/SocketList/" + + std::to_string(cwndWindow) + "/CongestionWindow", + CwndTrace); } -static void CwndChange(uint32_t oldCwnd, uint32_t newCwnd){ - std::ofstream fPlotQueue(tracesPath + "cwnd.txt", std::ios::out | std::ios::app); - fPlotQueue << Simulator::Now().GetSeconds() << " " << newCwnd / segmentSize << " " << newCwnd << std::endl; +static void CwndChange(uint32_t oldCwnd, uint32_t newCwnd) { + std::ofstream fPlotQueue(tracesPath + "cwnd.txt", + std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now().GetSeconds() << " " << newCwnd / segmentSize + << " " << newCwnd << std::endl; fPlotQueue.close(); } -void InstallBulkSend(Ptr node, Ipv4Address address, uint16_t port, std::string socketFactory, - uint32_t nodeId, uint32_t cwndWindow, Callback CwndTrace, uint32_t maxBytesToSend, Time startTime){ - BulkSendHelper source(socketFactory, InetSocketAddress(address, port)); - source.SetAttribute("MaxBytes", UintegerValue(maxBytesToSend)); - ApplicationContainer sourceApps = source.Install(node); - sourceApps.Start(startTime); - sourceApps.Stop (stopTimeTCP); - if(storeTraces == false){ - Simulator::Schedule(startTime + Seconds(0.001), &TraceCwnd, nodeId, cwndWindow, CwndTrace); - } +void InstallBulkSend(Ptr node, Ipv4Address address, uint16_t port, + std::string socketFactory, uint32_t nodeId, + uint32_t cwndWindow, + Callback CwndTrace, + uint32_t maxBytesToSend, Time startTime) { + BulkSendHelper source(socketFactory, InetSocketAddress(address, port)); + source.SetAttribute("MaxBytes", UintegerValue(maxBytesToSend)); + ApplicationContainer sourceApps = source.Install(node); + sourceApps.Start(startTime); + sourceApps.Stop(stopTimeTCP); + if (storeTraces == false) { + Simulator::Schedule(startTime + Seconds(0.001), &TraceCwnd, nodeId, + cwndWindow, CwndTrace); + } } -void InstallPacketSink(Ptr node, uint16_t port, std::string socketFactory, Time startTime, Time stopTime){ - PacketSinkHelper sink (socketFactory, InetSocketAddress(Ipv4Address::GetAny(), port)); - ApplicationContainer sinkApps = sink.Install(node); - sinker = StaticCast(sinkApps.Get(0)); - sinkApps.Start(startTime); - sinkApps.Stop(stopTime); +void InstallPacketSink(Ptr node, uint16_t port, std::string socketFactory, + Time startTime, Time stopTime) { + PacketSinkHelper sink(socketFactory, + InetSocketAddress(Ipv4Address::GetAny(), port)); + ApplicationContainer sinkApps = sink.Install(node); + sinker = StaticCast(sinkApps.Get(0)); + sinkApps.Start(startTime); + sinkApps.Stop(stopTime); } -static void DropAtQueue(Ptr stream, Ptr item){ - *stream->GetStream() << Simulator::Now().GetSeconds() << " 1" << std::endl; - packetsDroppedInQueue++; +static void DropAtQueue(Ptr stream, + Ptr item) { + *stream->GetStream() << Simulator::Now().GetSeconds() << " 1" << std::endl; + packetsDroppedInQueue++; } -void PacketsInQueueDisc (uint32_t oldValue, uint32_t newValue){ - std::ofstream fPlotQueue (std::stringstream(tracesPath + "pktsQueueDisc.txt").str().c_str(), std::ios::out | std::ios::app); - fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; - fPlotQueue.close(); +void PacketsInQueueDisc(uint32_t oldValue, uint32_t newValue) { + std::ofstream fPlotQueue( + std::stringstream(tracesPath + "pktsQueueDisc.txt").str().c_str(), + std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; + fPlotQueue.close(); } -void PacketsInDroptail (uint32_t oldValue, uint32_t newValue){ - std::ofstream fPlotQueue(std::stringstream(tracesPath + "pktsDropTail.txt").str().c_str(), std::ios::out | std::ios::app); - fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; - fPlotQueue.close(); +void PacketsInDroptail(uint32_t oldValue, uint32_t newValue) { + std::ofstream fPlotQueue( + std::stringstream(tracesPath + "pktsDropTail.txt").str().c_str(), + std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; + fPlotQueue.close(); } -void ExaminePacket(Ptr< const Packet > packet){ - // Extract TCP Header from the packet - TcpHeader tcpHeader; - packet->PeekHeader(tcpHeader); - uint32_t payloadSize = packet->GetSize(); +void ExaminePacket(Ptr packet) { + // Extract TCP Header from the packet + TcpHeader tcpHeader; + packet->PeekHeader(tcpHeader); + uint32_t payloadSize = packet->GetSize(); - // Extract the SEQ and ACK numbers - uint32_t seq = tcpHeader.GetSequenceNumber().GetValue(); - uint32_t ack = tcpHeader.GetAckNumber().GetValue(); + // Extract the SEQ and ACK numbers + uint32_t seq = tcpHeader.GetSequenceNumber().GetValue(); + uint32_t ack = tcpHeader.GetAckNumber().GetValue(); - std::cout << "[TCP PACKET] [SEQ: " << seq << "] [ACK: " << ack << "] [Payload Length: " << payloadSize << "] PacketUid: " << packet->GetUid() << std::endl; + std::cout << "[TCP PACKET] [SEQ: " << seq << "] [ACK: " << ack + << "] [Payload Length: " << payloadSize + << "] PacketUid: " << packet->GetUid() << std::endl; } -int main (int argc, char *argv[]){ - // Command line arguments - CommandLine cmd; - cmd.AddValue("tcpVariantId", "TCP variant", tcpVariantId); - cmd.AddValue("enableSack", "Enable/disable sack in TCP", enableSack); - cmd.AddValue("seed", "The random seed", seed); - cmd.AddValue("simStopTime", "The simulation stop time", stopTimeSimulation); - cmd.AddValue("intervalTCP", "The TCP interval", intervalTCP); - cmd.AddValue("initialCwnd", "Initial CWND window", initialCwnd); - cmd.AddValue("bytesToSend", "Number of bytes to send", bytes_to_send); - cmd.Parse(argc, argv); - - // Set Random Seed - Random::seed(seed); - - // TCP Recovery Algorithm - Config::SetDefault("ns3::TcpL4Protocol::RecoveryType", TypeIdValue(TypeId::LookupByName(tcpRecovery))); - - // Set Congestion Control Algorithm - Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue(tcpVariantId)); - Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(1073741824)); - Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(1073741824)); - - // Set default initial congestion window - Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(initialCwnd)); - - // Set default delayed ack count to a specified value - Config::SetDefault("ns3::TcpSocket::DelAckTimeout", TimeValue(Time(delAckTimeout))); - Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(delAckCount)); - //Config::SetDefault("ns3::TcpSocket::SetTcpNoDelay", BooleanValue(true)); - - // Set default segment size of TCP packet to a specified value - Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(segmentSize)); - - // Enable/Disable SACK in TCP - Config::SetDefault("ns3::TcpSocketBase::Sack", BooleanValue(enableSack)); - - Config::SetDefault("ns3::TcpSocketBase::MinRto", TimeValue(Seconds(minRTO))); - - NodeContainer leftNodes, rightNodes, routers; - routers.Create(2); - leftNodes.Create(1); - rightNodes.Create(1); - - Names::Add("Router1", routers.Get(0)); - Names::Add("Router2", routers.Get(1)); - Names::Add("Sender", leftNodes.Get(0)); - Names::Add("Receiver", rightNodes.Get(0)); - - DataRate b_access(bandwidth_access); - DataRate b_bottleneck(bandwidth_bottleneck); - Time d_access(delay_access); - Time d_bottleneck(delay_bottleneck); - Time d_serialization(delay_serialization); - - uint32_t max_bottleneck_bytes = static_cast(((std::min(b_access, b_bottleneck).GetBitRate () / 8) * (((d_access * 2) + d_bottleneck) * 2 + d_serialization).GetSeconds())); - uint32_t projected_queue_max_packets = std::ceil(max_bottleneck_bytes/MTU_bytes); - - // Set Droptail queue size to 1 packet - Config::SetDefault("ns3::DropTailQueue::MaxSize", StringValue("1p")); - - // Create the point-to-point link helpers and connect two router nodes - PointToPointHelper pointToPointRouter; - pointToPointRouter.SetDeviceAttribute("DataRate", StringValue(bandwidth_bottleneck)); - pointToPointRouter.SetChannelAttribute("Delay", StringValue(delay_bottleneck)); - - NetDeviceContainer r1r2ND = pointToPointRouter.Install(routers.Get(0), routers.Get(1)); - - // Create the point-to-point link helpers and connect leaf nodes to router - PointToPointHelper pointToPointLeaf; - pointToPointLeaf.SetDeviceAttribute("DataRate", StringValue(bandwidth_access)); - pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); - - NetDeviceContainer leftToRouter = pointToPointLeaf.Install(leftNodes.Get(0), routers.Get(0)); - NetDeviceContainer routerToRight = pointToPointLeaf.Install(routers.Get(1), rightNodes.Get(0)); - - InternetStackHelper internetStack; - internetStack.Install(leftNodes); - internetStack.Install(rightNodes); - internetStack.Install(routers); - - Ipv4AddressHelper ipAddresses("10.0.0.0", "255.255.255.0"); - Ipv4InterfaceContainer r1r2IPAddress = ipAddresses.Assign(r1r2ND); - ipAddresses.NewNetwork(); - Ipv4InterfaceContainer leftToRouterIPAddress = ipAddresses.Assign(leftToRouter); - ipAddresses.NewNetwork(); - Ipv4InterfaceContainer routerToRightIPAddress = ipAddresses.Assign(routerToRight); - ipAddresses.NewNetwork(); - - Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - - Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, projected_queue_max_packets))); - - TrafficControlHelper tch; - tch.SetRootQueueDisc("ns3::PfifoFastQueueDisc"); - QueueDiscContainer qd; - tch.Uninstall(routers.Get(0)->GetDevice(0)); - qd.Add(tch.Install(routers.Get(0)->GetDevice(0)).Get(0)); - - /* Trace the QueueDisc Queue size */ - if(storeTraces == false){ - Ptr q = qd.Get(0); - q->TraceConnectWithoutContext("PacketsInQueue", MakeCallback(&PacketsInQueueDisc)); - } - - /* Trace the DropTail Queue size */ - if(storeTraces){ - Ptr nd = routers.Get(0)->GetDevice(0); - Ptr ptpnd = DynamicCast(nd); - Ptr> queue = ptpnd->GetQueue(); - queue->TraceConnectWithoutContext("PacketsInQueue", MakeCallback(&PacketsInDroptail)); - } - - /* Trace packets dropped by the QueueDisc Queue */ - if(storeTraces){ - AsciiTraceHelper ascii; - Ptr streamWrapper; - streamWrapper = ascii.CreateFileStream(tracesPath + "droppedQueueDisc.txt"); - qd.Get(0)->TraceConnectWithoutContext("Drop", MakeBoundCallback (&DropAtQueue, streamWrapper)); - } - - netDeviceToDropPacket = &r1r2ND; - /* Callback to the ExaminePacket */ - r1r2ND.Get(0)->TraceConnectWithoutContext("MacTx", MakeCallback(&ExaminePacket)); - - /* Packet Printing is mandatory for the Packet Drop Test */ - Packet::EnablePrinting(); - - uint16_t server_port = 50000; - /* Install packet sink at receiver side */ - InstallPacketSink(rightNodes.Get(0), server_port, socketFactory, Seconds(0.01), stopTimeSimulation); - - /* Install BulkSend application */ - InstallBulkSend(leftNodes.Get(0), routerToRightIPAddress.GetAddress(1), server_port, socketFactory, 2, 0, MakeCallback(&CwndChange), bytes_to_send, Seconds(0.2)); - - if(storeTraces){ - pointToPointLeaf.EnablePcapAll(tracesPath); - } - - Simulator::Stop(stopTimeSimulation); - Simulator::Run(); - Simulator::Destroy(); - return 0; +int main(int argc, char *argv[]) { + // Command line arguments + CommandLine cmd; + cmd.AddValue("tcpVariantId", "TCP variant", tcpVariantId); + cmd.AddValue("enableSack", "Enable/disable sack in TCP", enableSack); + cmd.AddValue("seed", "The random seed", seed); + cmd.AddValue("simStopTime", "The simulation stop time", stopTimeSimulation); + cmd.AddValue("intervalTCP", "The TCP interval", intervalTCP); + cmd.AddValue("initialCwnd", "Initial CWND window", initialCwnd); + cmd.AddValue("bytesToSend", "Number of bytes to send", bytes_to_send); + cmd.Parse(argc, argv); + + // Set Random Seed + Random::seed(seed); + + // TCP Recovery Algorithm + Config::SetDefault("ns3::TcpL4Protocol::RecoveryType", + TypeIdValue(TypeId::LookupByName(tcpRecovery))); + + // Set Congestion Control Algorithm + Config::SetDefault("ns3::TcpL4Protocol::SocketType", + StringValue(tcpVariantId)); + Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(1073741824)); + Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(1073741824)); + + // Set default initial congestion window + Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(initialCwnd)); + + // Set default delayed ack count to a specified value + Config::SetDefault("ns3::TcpSocket::DelAckTimeout", + TimeValue(Time(delAckTimeout))); + Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(delAckCount)); + // Config::SetDefault("ns3::TcpSocket::SetTcpNoDelay", BooleanValue(true)); + + // Set default segment size of TCP packet to a specified value + Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(segmentSize)); + + // Enable/Disable SACK in TCP + Config::SetDefault("ns3::TcpSocketBase::Sack", BooleanValue(enableSack)); + + Config::SetDefault("ns3::TcpSocketBase::MinRto", TimeValue(Seconds(minRTO))); + + NodeContainer leftNodes, rightNodes, routers; + routers.Create(2); + leftNodes.Create(1); + rightNodes.Create(1); + + Names::Add("Router1", routers.Get(0)); + Names::Add("Router2", routers.Get(1)); + Names::Add("Sender", leftNodes.Get(0)); + Names::Add("Receiver", rightNodes.Get(0)); + + DataRate b_access(bandwidth_access); + DataRate b_bottleneck(bandwidth_bottleneck); + Time d_access(delay_access); + Time d_bottleneck(delay_bottleneck); + Time d_serialization(delay_serialization); + + uint32_t max_bottleneck_bytes = static_cast( + ((std::min(b_access, b_bottleneck).GetBitRate() / 8) * + (((d_access * 2) + d_bottleneck) * 2 + d_serialization).GetSeconds())); + uint32_t projected_queue_max_packets = + std::ceil(max_bottleneck_bytes / MTU_bytes); + + // Set Droptail queue size to 1 packet + Config::SetDefault("ns3::DropTailQueue::MaxSize", StringValue("1p")); + + // Create the point-to-point link helpers and connect two router nodes + PointToPointHelper pointToPointRouter; + pointToPointRouter.SetDeviceAttribute("DataRate", + StringValue(bandwidth_bottleneck)); + pointToPointRouter.SetChannelAttribute("Delay", + StringValue(delay_bottleneck)); + + NetDeviceContainer r1r2ND = + pointToPointRouter.Install(routers.Get(0), routers.Get(1)); + + // Create the point-to-point link helpers and connect leaf nodes to router + PointToPointHelper pointToPointLeaf; + pointToPointLeaf.SetDeviceAttribute("DataRate", + StringValue(bandwidth_access)); + pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); + + NetDeviceContainer leftToRouter = + pointToPointLeaf.Install(leftNodes.Get(0), routers.Get(0)); + NetDeviceContainer routerToRight = + pointToPointLeaf.Install(routers.Get(1), rightNodes.Get(0)); + + InternetStackHelper internetStack; + internetStack.Install(leftNodes); + internetStack.Install(rightNodes); + internetStack.Install(routers); + + Ipv4AddressHelper ipAddresses("10.0.0.0", "255.255.255.0"); + Ipv4InterfaceContainer r1r2IPAddress = ipAddresses.Assign(r1r2ND); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer leftToRouterIPAddress = + ipAddresses.Assign(leftToRouter); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer routerToRightIPAddress = + ipAddresses.Assign(routerToRight); + ipAddresses.NewNetwork(); + + Ipv4GlobalRoutingHelper::PopulateRoutingTables(); + + // Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", + // QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, + // projected_queue_max_packets))); + Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", + QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, 1))); + + TrafficControlHelper tch; + tch.SetRootQueueDisc("ns3::PfifoFastQueueDisc"); + QueueDiscContainer qd; + tch.Uninstall(routers.Get(0)->GetDevice(0)); + qd.Add(tch.Install(routers.Get(0)->GetDevice(0)).Get(0)); + + /* Trace the QueueDisc Queue size */ + if (storeTraces == false) { + Ptr q = qd.Get(0); + q->TraceConnectWithoutContext("PacketsInQueue", + MakeCallback(&PacketsInQueueDisc)); + } + + /* Trace the DropTail Queue size */ + if (storeTraces) { + Ptr nd = routers.Get(0)->GetDevice(0); + Ptr ptpnd = DynamicCast(nd); + Ptr> queue = ptpnd->GetQueue(); + queue->TraceConnectWithoutContext("PacketsInQueue", + MakeCallback(&PacketsInDroptail)); + } + + /* Trace packets dropped by the QueueDisc Queue */ + if (storeTraces) { + AsciiTraceHelper ascii; + Ptr streamWrapper; + streamWrapper = ascii.CreateFileStream(tracesPath + "droppedQueueDisc.txt"); + qd.Get(0)->TraceConnectWithoutContext( + "Drop", MakeBoundCallback(&DropAtQueue, streamWrapper)); + } + + netDeviceToDropPacket = &r1r2ND; + /* Callback to the ExaminePacket */ + r1r2ND.Get(0)->TraceConnectWithoutContext("MacTx", + MakeCallback(&ExaminePacket)); + + /* Packet Printing is mandatory for the Packet Drop Test */ + Packet::EnablePrinting(); + + uint16_t server_port = 50000; + /* Install packet sink at receiver side */ + InstallPacketSink(rightNodes.Get(0), server_port, socketFactory, + Seconds(0.01), stopTimeSimulation); + + /* Install BulkSend application */ + InstallBulkSend(leftNodes.Get(0), routerToRightIPAddress.GetAddress(1), + server_port, socketFactory, 2, 0, MakeCallback(&CwndChange), + bytes_to_send, Seconds(0.2)); + + if (storeTraces) { + pointToPointLeaf.EnablePcapAll(tracesPath); + } + + Simulator::Stop(stopTimeSimulation); + Simulator::Run(); + Simulator::Destroy(); + return 0; } - From c9dd4c42284b9195323b0f6e36d70021444bad4a Mon Sep 17 00:00:00 2001 From: charliebarber Date: Wed, 6 Mar 2024 20:57:35 +0000 Subject: [PATCH 02/28] UDP setup on basic_congestion --- src/basic_congestion.cc | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/basic_congestion.cc b/src/basic_congestion.cc index 480b6e00..c1b421bf 100644 --- a/src/basic_congestion.cc +++ b/src/basic_congestion.cc @@ -319,6 +319,9 @@ int main(int argc, char *argv[]) { Ipv4InterfaceContainer routerToRightIPAddress = ipAddresses.Assign(routerToRight); ipAddresses.NewNetwork(); + Ipv4InterfaceContainer congestionToRouter0IPAddress = + ipAddresses.Assign(congestionSenderToRouter); + ipAddresses.NewNetwork(); Ipv4GlobalRoutingHelper::PopulateRoutingTables(); @@ -371,11 +374,13 @@ int main(int argc, char *argv[]) { /* Install packet sink at receiver side */ InstallPacketSink(rightNodes.Get(0), server_port, socketFactory, Seconds(0.01), stopTimeSimulation); + // InstallPacketSink(rightNodes.Get(0), server_port, "ns3::UdpSocketFactory", + // Seconds(0.01), stopTimeSimulation); /* Install BulkSend application */ - InstallBulkSend(leftNodes.Get(0), routerToRightIPAddress.GetAddress(1), - server_port, socketFactory, 2, 0, MakeCallback(&CwndChange), - bytes_to_send, Seconds(0.2)); + // InstallBulkSend(leftNodes.Get(0), routerToRightIPAddress.GetAddress(1), + // server_port, socketFactory, 2, 0, + // MakeCallback(&CwndChange), bytes_to_send, Seconds(0.2)); // Congestion PARAMETERS uint16_t serverPort = 50000; @@ -397,14 +402,24 @@ int main(int argc, char *argv[]) { // interval, receiverAddress, serverPort); // }); - SimulateCongestion(congestionNode.Get(0), startDelay, duration, numPackets, - packetSize, interval, receiverAddress, serverPort); + // SimulateCongestion(congestionNode.Get(0), startDelay, duration, numPackets, + // packetSize, interval, receiverAddress, serverPort); + + OnOffHelper onoff( + "ns3::UdpSocketFactory", + InetSocketAddress(routerToRightIPAddress.GetAddress(1), 50000)); + onoff.SetAttribute("PacketSize", UintegerValue(8)); + onoff.SetAttribute("DataRate", DataRateValue(DataRate("1kbps"))); + + ApplicationContainer app = onoff.Install(congestionNode.Get(0)); + app.Start(Seconds(1.0)); + app.Stop(Seconds(3.0)); if (storeTraces) { pointToPointLeaf.EnablePcapAll(tracesPath); } - Simulator::Stop(stopTimeSimulation); + // Simulator::Stop(stopTimeSimulation); Simulator::Run(); Simulator::Destroy(); return 0; From 9bd1391af81b00b8a5f39f0dd198b0636fc3f2d4 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Sat, 9 Mar 2024 17:06:01 +0000 Subject: [PATCH 03/28] :sparkles: add basic congestion policy --- libs/basic_congestion.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 libs/basic_congestion.h diff --git a/libs/basic_congestion.h b/libs/basic_congestion.h new file mode 100644 index 00000000..febbe6c3 --- /dev/null +++ b/libs/basic_congestion.h @@ -0,0 +1,34 @@ +#ifndef BASIC_CONGESTION_POLICY_H +#define BASIC_CONGESTION_POLICY_H + + +namespace ns3 +{ + + +template +class BasicCongestionPolicy +{ + static_assert(MAX_USAGE_PERCENTAGE > 0 && MAX_USAGE_PERCENTAGE <= 100, "MAX_USAGE_PERCENTAGE must be between 1 and 100"); + + public: + static bool isCongested(ns3::Queue* queue); +}; + +template <> +bool BasicCongestionPolicy<100>::isCongested(ns3::Queue* queue) +{ + return queue->GetNPackets() > queue->GetMaxSize().GetValue(); +} + +template +bool BasicCongestionPolicy::isCongested(ns3::Queue* queue) +{ + return queue->GetNPackets() * 100 > queue->GetMaxSize().GetValue() * MAX_USAGE_PERCENTAGE; +} + + + +} // namespace ns3 + +#endif From 2056fe7af7d40e5e674835f9821e5dd3ab47fd60 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Sat, 9 Mar 2024 17:06:34 +0000 Subject: [PATCH 04/28] :bug: fix the congestion policy checking --- libs/frr_queue.h | 2 +- libs/modulo_congestion_policy.h | 3 +-- libs/random_congestion_policy.h | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libs/frr_queue.h b/libs/frr_queue.h index 15bea576..d6e5b131 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -91,7 +91,7 @@ template bool FRRQueue::Enqueue(Ptr packet) { NS_LOG_FUNCTION(this << packet); - if (m_congestionPolicy.isCongested(GetContainer())) + if (m_congestionPolicy.isCongested(this)) { NS_LOG_LOGIC("Congested Route, Rerouting packet: " << packet); ForwardToAlternateTarget(packet); diff --git a/libs/modulo_congestion_policy.h b/libs/modulo_congestion_policy.h index 561f4f75..b4d14723 100644 --- a/libs/modulo_congestion_policy.h +++ b/libs/modulo_congestion_policy.h @@ -12,8 +12,7 @@ class ModuloCongestionPolicy public: - template - bool isCongested(const CONTAINER& container) + bool isCongested(ns3::Queue* queue) { increment(); return counter; diff --git a/libs/random_congestion_policy.h b/libs/random_congestion_policy.h index a377e81e..b0130ce9 100644 --- a/libs/random_congestion_policy.h +++ b/libs/random_congestion_policy.h @@ -15,8 +15,7 @@ class RandomCongestionPolicy RandomCongestionPolicy() = default; - template - bool isCongested(const CONTAINER& container) const + bool isCongested(ns3::Queue* queue) const { std::random_device rd; std::mt19937 gen(rd()); From ff3dc05819b08f04060be9ec60f927577d88c276 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Sat, 9 Mar 2024 17:06:57 +0000 Subject: [PATCH 05/28] :sparkles: add basic_congestion policy --- src/basic_congestion.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/basic_congestion.cc b/src/basic_congestion.cc index c1b421bf..406b6fb7 100644 --- a/src/basic_congestion.cc +++ b/src/basic_congestion.cc @@ -14,10 +14,23 @@ #include "ns3/traffic-control-module.h" #include "../libs/random/random.hpp" +#include "../libs/basic_congestion.h" + +#include "../libs/frr_queue.h" +#include "../libs/lfa_policy.h" + + using namespace ns3; using Random = effolkronium::random_static; +using CongestionPolicy = BasicCongestionPolicy<100>; +using FRRPolicy = LFAPolicy; + +using SimulationQueue = FRRQueue; + +NS_OBJECT_ENSURE_REGISTERED(SimulationQueue); + // ---------------------------------------------------- // // --- BEGIN OF SIMULATION CONFIGURATION PARAMETERS --- // // ---------------------------------------------------- // @@ -281,6 +294,7 @@ int main(int argc, char *argv[]) { // Create the point-to-point link helpers and connect two router nodes PointToPointHelper pointToPointRouter; + pointToPointRouter.SetQueue(SimulationQueue::getQueueString()); pointToPointRouter.SetDeviceAttribute("DataRate", StringValue(bandwidth_bottleneck)); pointToPointRouter.SetChannelAttribute("Delay", @@ -291,6 +305,7 @@ int main(int argc, char *argv[]) { // Create the point-to-point link helpers and connect leaf nodes to router PointToPointHelper pointToPointLeaf; + pointToPointLeaf.SetQueue(SimulationQueue::getQueueString()); pointToPointLeaf.SetDeviceAttribute("DataRate", StringValue(bandwidth_access)); pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); From 201ca0a8461b4c196bc93e3d9c617fdfe1f795bd Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Sat, 9 Mar 2024 18:30:51 +0000 Subject: [PATCH 06/28] :construction: WIP on basic congestion --- entrypoint.sh | 2 +- libs/basic_congestion.h | 4 +-- libs/frr_queue.h | 20 ++++++++----- src/basic_congestion.cc | 65 ++++++++++++++++++++++++++++++++++------- 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 6d49bcd4..9bbfdb57 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -8,4 +8,4 @@ cp user_src/* scratch/ export NS_LOG=FRRQueue=level_all ./ns3 build -./ns3 run "scratch/$1" >traces/output.log 2>&1 +./ns3 run "scratch/$1" > traces/output.log diff --git a/libs/basic_congestion.h b/libs/basic_congestion.h index febbe6c3..b3a0beef 100644 --- a/libs/basic_congestion.h +++ b/libs/basic_congestion.h @@ -18,13 +18,13 @@ class BasicCongestionPolicy template <> bool BasicCongestionPolicy<100>::isCongested(ns3::Queue* queue) { - return queue->GetNPackets() > queue->GetMaxSize().GetValue(); + return queue->GetNPackets() >= queue->GetMaxSize().GetValue(); } template bool BasicCongestionPolicy::isCongested(ns3::Queue* queue) { - return queue->GetNPackets() * 100 > queue->GetMaxSize().GetValue() * MAX_USAGE_PERCENTAGE; + return queue->GetNPackets() * 100 >= queue->GetMaxSize().GetValue() * MAX_USAGE_PERCENTAGE; } diff --git a/libs/frr_queue.h b/libs/frr_queue.h index d6e5b131..c33a4683 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -29,6 +29,7 @@ class FRRQueue : public Queue using Queue::DoRemove; using Queue::DoPeek; + int m_uid; NS_LOG_TEMPLATE_DECLARE; @@ -40,7 +41,7 @@ class FRRQueue : public Queue virtual Ptr Remove(void) override; virtual Ptr Peek() const override; public: - + static int s_uid; FRR_POLICY m_frrPolicy; CONGESTION_POLICY m_congestionPolicy; @@ -54,10 +55,14 @@ class FRRQueue : public Queue static const std::string& getQueueString(); }; +template +int FRRQueue::s_uid = 0; + template FRRQueue::FRRQueue() : Queue(), + m_uid(s_uid++), NS_LOG_TEMPLATE_DEFINE("FRRQueue") { NS_LOG_FUNCTION(this); @@ -67,7 +72,7 @@ FRRQueue::FRRQueue() template FRRQueue::~FRRQueue() { - NS_LOG_FUNCTION(this); + //NS_LOG_FUNCTION(this); } template @@ -93,13 +98,14 @@ bool FRRQueue::Enqueue(Ptr packet) NS_LOG_FUNCTION(this << packet); if (m_congestionPolicy.isCongested(this)) { - NS_LOG_LOGIC("Congested Route, Rerouting packet: " << packet); + NS_LOG_LOGIC("(" << m_uid << ") Congested Route, Rerouting packet: " << packet); ForwardToAlternateTarget(packet); - NS_LOG_LOGIC("Rerouting complete"); + NS_LOG_LOGIC("(" << m_uid << ") Rerouting complete"); return false; } - NS_LOG_LOGIC("Enqueued " << packet << " to " << GetContainer().size() << " packets in queue."); + NS_LOG_LOGIC("(" << m_uid << ") Enqueued " << packet << " to " << GetNPackets() << " packets in queue."); DoEnqueue(GetContainer().end(), packet); + NS_LOG_LOGIC("(" << m_uid << ") Enqueued " << packet << " to " << GetNPackets() << " packets in queue."); return true; } @@ -138,8 +144,8 @@ Ptr FRRQueue::Peek() const template void FRRQueue::ForwardToAlternateTarget(Ptr packet) { - auto alternativeTarget = m_frrPolicy.selectAlternativeTarget(); - alternativeTarget->Send(packet, alternativeTarget->GetAddress(), 0x0800); + Ptr alternativeTarget = m_frrPolicy.selectAlternativeTarget(); + if (alternativeTarget) alternativeTarget->Send(packet, alternativeTarget->GetAddress(), 0x0800); } template diff --git a/src/basic_congestion.cc b/src/basic_congestion.cc index 406b6fb7..15d2f6ef 100644 --- a/src/basic_congestion.cc +++ b/src/basic_congestion.cc @@ -24,7 +24,7 @@ using namespace ns3; using Random = effolkronium::random_static; -using CongestionPolicy = BasicCongestionPolicy<100>; +using CongestionPolicy = BasicCongestionPolicy<99>; using FRRPolicy = LFAPolicy; using SimulationQueue = FRRQueue; @@ -35,6 +35,25 @@ NS_OBJECT_ENSURE_REGISTERED(SimulationQueue); // --- BEGIN OF SIMULATION CONFIGURATION PARAMETERS --- // // ---------------------------------------------------- // +template +Ptr getDevice(const NetDeviceContainer& devices) +{ + return devices.Get(INDEX)->GetObject(); +} + +template +Ptr getQueue(const NetDeviceContainer& devices) +{ + return DynamicCast(getDevice(devices)->GetQueue()); +} + +template +void setAlternateTarget(const NetDeviceContainer& devices, Ptr target) +{ + getQueue(devices)->addAlternateTargets(target); +} + + // Random Seed uint32_t seed = 1; @@ -59,8 +78,8 @@ Time stopTimeSimulation = Seconds(5000); Time intervalTCP = Seconds(1); // ---[TCP PARAMETERS] --- -uint32_t segmentSize = 1024; -uint32_t MTU_bytes = segmentSize + 54; +uint32_t segmentSize = 32; //1024; +uint32_t MTU_bytes = 38;// segmentSize + 54; uint8_t delAckCount = 1; uint8_t initialCwnd = 1; // std::string delAckTimeout = "200ms"; @@ -221,6 +240,8 @@ void SimulateCongestion(Ptr congestionNode, Time startDelay, } int main(int argc, char *argv[]) { + LogComponentEnable("FRRQueue", LOG_LEVEL_LOGIC); + NS_LOG_INFO("Creating Topology"); // Command line arguments CommandLine cmd; cmd.AddValue("tcpVariantId", "TCP variant", tcpVariantId); @@ -263,12 +284,13 @@ int main(int argc, char *argv[]) { Config::SetDefault("ns3::TcpSocketBase::MinRto", TimeValue(Seconds(minRTO))); NodeContainer leftNodes, rightNodes, routers; - routers.Create(2); + routers.Create(3); leftNodes.Create(1); rightNodes.Create(1); Names::Add("Router1", routers.Get(0)); Names::Add("Router2", routers.Get(1)); + Names::Add("Router3", routers.Get(2)); Names::Add("Sender", leftNodes.Get(0)); Names::Add("Receiver", rightNodes.Get(0)); @@ -290,7 +312,7 @@ int main(int argc, char *argv[]) { std::ceil(max_bottleneck_bytes / MTU_bytes); // Set Droptail queue size to 1 packet - Config::SetDefault("ns3::DropTailQueue::MaxSize", StringValue("1p")); + Config::SetDefault(SimulationQueue::getQueueString() + "::MaxSize", StringValue("100p")); // Create the point-to-point link helpers and connect two router nodes PointToPointHelper pointToPointRouter; @@ -300,12 +322,29 @@ int main(int argc, char *argv[]) { pointToPointRouter.SetChannelAttribute("Delay", StringValue(delay_bottleneck)); + + + // Draw a ring topology between R1 -> R2 -> R3 + /* + * R3 + * / \ + * / \ + * CS --- R1----R2 --- R + */ NetDeviceContainer r1r2ND = pointToPointRouter.Install(routers.Get(0), routers.Get(1)); - + + NetDeviceContainer r1r3ND = + pointToPointRouter.Install(routers.Get(0), routers.Get(2)); + NetDeviceContainer r3r2ND = + pointToPointRouter.Install(routers.Get(2), routers.Get(1)); + + setAlternateTarget<0>(r1r2ND, getDevice<0>(r1r3ND)); + //setAlternateTarget<0>(r1r2ND, getDevice<0>(devices02)); + // Create the point-to-point link helpers and connect leaf nodes to router PointToPointHelper pointToPointLeaf; - pointToPointLeaf.SetQueue(SimulationQueue::getQueueString()); + //pointToPointLeaf.SetQueue(SimulationQueue::getQueueString()); pointToPointLeaf.SetDeviceAttribute("DataRate", StringValue(bandwidth_access)); pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); @@ -338,13 +377,19 @@ int main(int argc, char *argv[]) { ipAddresses.Assign(congestionSenderToRouter); ipAddresses.NewNetwork(); + + Ipv4InterfaceContainer r1r3IPAddress = ipAddresses.Assign(r1r3ND); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer r3r2IPAddress = ipAddresses.Assign(r3r2ND); + ipAddresses.NewNetwork(); + Ipv4GlobalRoutingHelper::PopulateRoutingTables(); // Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", // QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, // projected_queue_max_packets))); Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", - QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, 1))); + QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, 100))); TrafficControlHelper tch; tch.SetRootQueueDisc("ns3::PfifoFastQueueDisc"); @@ -424,14 +469,14 @@ int main(int argc, char *argv[]) { "ns3::UdpSocketFactory", InetSocketAddress(routerToRightIPAddress.GetAddress(1), 50000)); onoff.SetAttribute("PacketSize", UintegerValue(8)); - onoff.SetAttribute("DataRate", DataRateValue(DataRate("1kbps"))); + onoff.SetAttribute("DataRate", DataRateValue(DataRate("200kbps"))); ApplicationContainer app = onoff.Install(congestionNode.Get(0)); app.Start(Seconds(1.0)); app.Stop(Seconds(3.0)); if (storeTraces) { - pointToPointLeaf.EnablePcapAll(tracesPath); + pointToPointRouter.EnablePcapAll(tracesPath); } // Simulator::Stop(stopTimeSimulation); From 0528da7c11c58756d52aca5f34af233152245e3b Mon Sep 17 00:00:00 2001 From: charliebarber Date: Sat, 9 Mar 2024 18:42:54 +0000 Subject: [PATCH 07/28] Simple changed + format --- src/simple_dumbbell_topo.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/simple_dumbbell_topo.cc b/src/simple_dumbbell_topo.cc index 80e9fc86..a54e0c72 100644 --- a/src/simple_dumbbell_topo.cc +++ b/src/simple_dumbbell_topo.cc @@ -71,12 +71,11 @@ std::string delay_serialization = "1.9ms"; NetDeviceContainer* netDeviceToDropPacket = NULL; - // -------------------------------------------------- // // --- END OF SIMULATION CONFIGURATION PARAMETERS --- // // -------------------------------------------------- // -// Global Variables +// Global Vars Ptr sinker; int packetsDroppedInQueue = 0; @@ -164,9 +163,9 @@ void ExaminePacket(Ptr packet) packet->PeekHeader(tcpHeader); uint32_t payloadSize = packet->GetSize(); - // Extract the SEQ and ACK numbers - uint32_t seq = tcpHeader.GetSequenceNumber().GetValue(); - uint32_t ack = tcpHeader.GetAckNumber().GetValue(); + // Extract the SEQ and ACK numbers + uint32_t seq = tcpHeader.GetSequenceNumber().GetValue(); + uint32_t ack = tcpHeader.GetAckNumber().GetValue(); std::cout << "[TCP PACKET] [SEQ: " << seq << "] [ACK: " << ack << "] [Payload Length: " << payloadSize << "] PacketUid: " << packet->GetUid() << std::endl; From e61f7e100011e038e993fc2159f8e2529ff50171 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Sat, 9 Mar 2024 18:44:55 +0000 Subject: [PATCH 08/28] :art: format files --- src/basic_congestion.cc | 603 +++++++++++++++++++++------------------- 1 file changed, 312 insertions(+), 291 deletions(-) diff --git a/src/basic_congestion.cc b/src/basic_congestion.cc index c1b421bf..d6ec7f14 100644 --- a/src/basic_congestion.cc +++ b/src/basic_congestion.cc @@ -68,7 +68,7 @@ std::string delay_bottleneck = "20ms"; std::string delay_serialization = "1.9ms"; // ---[POINTER TO THE DEVICE THAT WILL IMPLEMENT PACKET DROPING] -NetDeviceContainer *netDeviceToDropPacket = NULL; +NetDeviceContainer* netDeviceToDropPacket = NULL; // -------------------------------------------------- // // --- END OF SIMULATION CONFIGURATION PARAMETERS --- // @@ -84,82 +84,91 @@ uint32_t bytes_to_send = 10000; uint32_t cnt_packets = 0; void TraceCwnd(uint32_t node, uint32_t cwndWindow, - Callback CwndTrace) { - Config::ConnectWithoutContext( - "/NodeList/" + std::to_string(node) + "/$ns3::TcpL4Protocol/SocketList/" + - std::to_string(cwndWindow) + "/CongestionWindow", - CwndTrace); + Callback CwndTrace) +{ + Config::ConnectWithoutContext("/NodeList/" + std::to_string(node) + + "/$ns3::TcpL4Protocol/SocketList/" + + std::to_string(cwndWindow) + + "/CongestionWindow", + CwndTrace); } -static void CwndChange(uint32_t oldCwnd, uint32_t newCwnd) { - std::ofstream fPlotQueue(tracesPath + "cwnd.txt", - std::ios::out | std::ios::app); - fPlotQueue << Simulator::Now().GetSeconds() << " " << newCwnd / segmentSize - << " " << newCwnd << std::endl; - fPlotQueue.close(); +static void CwndChange(uint32_t oldCwnd, uint32_t newCwnd) +{ + std::ofstream fPlotQueue(tracesPath + "cwnd.txt", + std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now().GetSeconds() << " " << newCwnd / segmentSize + << " " << newCwnd << std::endl; + fPlotQueue.close(); } void InstallBulkSend(Ptr node, Ipv4Address address, uint16_t port, std::string socketFactory, uint32_t nodeId, uint32_t cwndWindow, Callback CwndTrace, - uint32_t maxBytesToSend, Time startTime) { - BulkSendHelper source(socketFactory, InetSocketAddress(address, port)); - source.SetAttribute("MaxBytes", UintegerValue(maxBytesToSend)); - ApplicationContainer sourceApps = source.Install(node); - sourceApps.Start(startTime); - sourceApps.Stop(stopTimeTCP); - if (storeTraces == false) { - Simulator::Schedule(startTime + Seconds(0.001), &TraceCwnd, nodeId, - cwndWindow, CwndTrace); - } + uint32_t maxBytesToSend, Time startTime) +{ + BulkSendHelper source(socketFactory, InetSocketAddress(address, port)); + source.SetAttribute("MaxBytes", UintegerValue(maxBytesToSend)); + ApplicationContainer sourceApps = source.Install(node); + sourceApps.Start(startTime); + sourceApps.Stop(stopTimeTCP); + if (storeTraces == false) { + Simulator::Schedule(startTime + Seconds(0.001), &TraceCwnd, nodeId, + cwndWindow, CwndTrace); + } } void InstallPacketSink(Ptr node, uint16_t port, std::string socketFactory, - Time startTime, Time stopTime) { - PacketSinkHelper sink(socketFactory, - InetSocketAddress(Ipv4Address::GetAny(), port)); - ApplicationContainer sinkApps = sink.Install(node); - sinker = StaticCast(sinkApps.Get(0)); - sinkApps.Start(startTime); - sinkApps.Stop(stopTime); + Time startTime, Time stopTime) +{ + PacketSinkHelper sink(socketFactory, + InetSocketAddress(Ipv4Address::GetAny(), port)); + ApplicationContainer sinkApps = sink.Install(node); + sinker = StaticCast(sinkApps.Get(0)); + sinkApps.Start(startTime); + sinkApps.Stop(stopTime); } static void DropAtQueue(Ptr stream, - Ptr item) { - *stream->GetStream() << Simulator::Now().GetSeconds() << " 1" << std::endl; - packetsDroppedInQueue++; + Ptr item) +{ + *stream->GetStream() << Simulator::Now().GetSeconds() << " 1" << std::endl; + packetsDroppedInQueue++; } -void PacketsInQueueDisc(uint32_t oldValue, uint32_t newValue) { - std::ofstream fPlotQueue( - std::stringstream(tracesPath + "pktsQueueDisc.txt").str().c_str(), - std::ios::out | std::ios::app); - fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; - fPlotQueue.close(); +void PacketsInQueueDisc(uint32_t oldValue, uint32_t newValue) +{ + std::ofstream fPlotQueue( + std::stringstream(tracesPath + "pktsQueueDisc.txt").str().c_str(), + std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; + fPlotQueue.close(); } -void PacketsInDroptail(uint32_t oldValue, uint32_t newValue) { - std::ofstream fPlotQueue( - std::stringstream(tracesPath + "pktsDropTail.txt").str().c_str(), - std::ios::out | std::ios::app); - fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; - fPlotQueue.close(); +void PacketsInDroptail(uint32_t oldValue, uint32_t newValue) +{ + std::ofstream fPlotQueue( + std::stringstream(tracesPath + "pktsDropTail.txt").str().c_str(), + std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now().GetSeconds() << " " << newValue << std::endl; + fPlotQueue.close(); } -void ExaminePacket(Ptr packet) { - // Extract TCP Header from the packet - TcpHeader tcpHeader; - packet->PeekHeader(tcpHeader); - uint32_t payloadSize = packet->GetSize(); +void ExaminePacket(Ptr packet) +{ + // Extract TCP Header from the packet + TcpHeader tcpHeader; + packet->PeekHeader(tcpHeader); + uint32_t payloadSize = packet->GetSize(); - // Extract the SEQ and ACK numbers - uint32_t seq = tcpHeader.GetSequenceNumber().GetValue(); - uint32_t ack = tcpHeader.GetAckNumber().GetValue(); + // Extract the SEQ and ACK numbers + uint32_t seq = tcpHeader.GetSequenceNumber().GetValue(); + uint32_t ack = tcpHeader.GetAckNumber().GetValue(); - std::cout << "[TCP PACKET] [SEQ: " << seq << "] [ACK: " << ack - << "] [Payload Length: " << payloadSize - << "] PacketUid: " << packet->GetUid() << std::endl; + std::cout << "[TCP PACKET] [SEQ: " << seq << "] [ACK: " << ack + << "] [Payload Length: " << payloadSize + << "] PacketUid: " << packet->GetUid() << std::endl; } // void SimulateCongestion(Ptr congestionNode, Time startDelay, @@ -184,243 +193,255 @@ void ExaminePacket(Ptr packet) { void SimulateCongestion(Ptr congestionNode, Time startDelay, Time duration, unsigned int numPackets, unsigned int packetSize, Time interval, - Ipv4Address receiverAddress, uint16_t port) { - // Create a UDP socket - Ptr socket = - Socket::CreateSocket(congestionNode, UdpSocketFactory::GetTypeId()); - InetSocketAddress receiverSocketAddress(receiverAddress, port); - - // Schedule sending packets using the UDP socket - Simulator::Schedule(startDelay, [socket, receiverSocketAddress, numPackets, - packetSize, interval]() { - for (unsigned int i = 0; i < numPackets; ++i) { - // std::cout << "sending packet " << i << std::endl; - Ptr packet = Create(packetSize); - int err = socket->SendTo(packet, packetSize, receiverSocketAddress); - if (err == -1) { - std::cout << "error sending packet " << i << std::endl; - } + Ipv4Address receiverAddress, uint16_t port) +{ + // Create a UDP socket + Ptr socket = + Socket::CreateSocket(congestionNode, UdpSocketFactory::GetTypeId()); + InetSocketAddress receiverSocketAddress(receiverAddress, port); + + // Schedule sending packets using the UDP socket + Simulator::Schedule(startDelay, [socket, receiverSocketAddress, numPackets, + packetSize, interval]() { + for (unsigned int i = 0; i < numPackets; ++i) { + // std::cout << "sending packet " << i << std::endl; + Ptr packet = Create(packetSize); + int err = socket->SendTo(packet, packetSize, receiverSocketAddress); + if (err == -1) { + std::cout << "error sending packet " << i << std::endl; + } + } + }); + + // Stop sending packets after the specified duration + Simulator::Schedule(startDelay + duration, &Socket::Close, socket); +} + +int main(int argc, char* argv[]) +{ + // Command line arguments + CommandLine cmd; + cmd.AddValue("tcpVariantId", "TCP variant", tcpVariantId); + cmd.AddValue("enableSack", "Enable/disable sack in TCP", enableSack); + cmd.AddValue("seed", "The random seed", seed); + cmd.AddValue("simStopTime", "The simulation stop time", stopTimeSimulation); + cmd.AddValue("intervalTCP", "The TCP interval", intervalTCP); + cmd.AddValue("initialCwnd", "Initial CWND window", initialCwnd); + cmd.AddValue("bytesToSend", "Number of bytes to send", bytes_to_send); + cmd.Parse(argc, argv); + + // Set Random Seed + Random::seed(seed); + + // TCP Recovery Algorithm + Config::SetDefault("ns3::TcpL4Protocol::RecoveryType", + TypeIdValue(TypeId::LookupByName(tcpRecovery))); + + // Set Congestion Control Algorithm + Config::SetDefault("ns3::TcpL4Protocol::SocketType", + StringValue(tcpVariantId)); + Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(1073741824)); + Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(1073741824)); + + // Set default initial congestion window + Config::SetDefault("ns3::TcpSocket::InitialCwnd", + UintegerValue(initialCwnd)); + + // Set default delayed ack count to a specified value + Config::SetDefault("ns3::TcpSocket::DelAckTimeout", + TimeValue(Time(delAckTimeout))); + Config::SetDefault("ns3::TcpSocket::DelAckCount", + UintegerValue(delAckCount)); + // Config::SetDefault("ns3::TcpSocket::SetTcpNoDelay", BooleanValue(true)); + + // Set default segment size of TCP packet to a specified value + Config::SetDefault("ns3::TcpSocket::SegmentSize", + UintegerValue(segmentSize)); + + // Enable/Disable SACK in TCP + Config::SetDefault("ns3::TcpSocketBase::Sack", BooleanValue(enableSack)); + + Config::SetDefault("ns3::TcpSocketBase::MinRto", + TimeValue(Seconds(minRTO))); + + NodeContainer leftNodes, rightNodes, routers; + routers.Create(2); + leftNodes.Create(1); + rightNodes.Create(1); + + Names::Add("Router1", routers.Get(0)); + Names::Add("Router2", routers.Get(1)); + Names::Add("Sender", leftNodes.Get(0)); + Names::Add("Receiver", rightNodes.Get(0)); + + // Congestion node setup + NodeContainer congestionNode; + congestionNode.Create(1); + Names::Add("CongestionSender", congestionNode.Get(0)); + + DataRate b_access(bandwidth_access); + DataRate b_bottleneck(bandwidth_bottleneck); + Time d_access(delay_access); + Time d_bottleneck(delay_bottleneck); + Time d_serialization(delay_serialization); + + uint32_t max_bottleneck_bytes = static_cast( + ((std::min(b_access, b_bottleneck).GetBitRate() / 8) * + (((d_access * 2) + d_bottleneck) * 2 + d_serialization).GetSeconds())); + uint32_t projected_queue_max_packets = + std::ceil(max_bottleneck_bytes / MTU_bytes); + + // Set Droptail queue size to 1 packet + Config::SetDefault("ns3::DropTailQueue::MaxSize", + StringValue("1p")); + + // Create the point-to-point link helpers and connect two router nodes + PointToPointHelper pointToPointRouter; + pointToPointRouter.SetDeviceAttribute("DataRate", + StringValue(bandwidth_bottleneck)); + pointToPointRouter.SetChannelAttribute("Delay", + StringValue(delay_bottleneck)); + + NetDeviceContainer r1r2ND = + pointToPointRouter.Install(routers.Get(0), routers.Get(1)); + + // Create the point-to-point link helpers and connect leaf nodes to router + PointToPointHelper pointToPointLeaf; + pointToPointLeaf.SetDeviceAttribute("DataRate", + StringValue(bandwidth_access)); + pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); + + NetDeviceContainer leftToRouter = + pointToPointLeaf.Install(leftNodes.Get(0), routers.Get(0)); + NetDeviceContainer routerToRight = + pointToPointLeaf.Install(routers.Get(1), rightNodes.Get(0)); + + // Link CongestioNSender to Router1 + NetDeviceContainer congestionSenderToRouter = + pointToPointLeaf.Install(congestionNode.Get(0), routers.Get(0)); + + InternetStackHelper internetStack; + internetStack.Install(leftNodes); + internetStack.Install(rightNodes); + internetStack.Install(routers); + internetStack.Install(congestionNode); + + Ipv4AddressHelper ipAddresses("10.0.0.0", "255.255.255.0"); + Ipv4InterfaceContainer r1r2IPAddress = ipAddresses.Assign(r1r2ND); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer leftToRouterIPAddress = + ipAddresses.Assign(leftToRouter); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer routerToRightIPAddress = + ipAddresses.Assign(routerToRight); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer congestionToRouter0IPAddress = + ipAddresses.Assign(congestionSenderToRouter); + ipAddresses.NewNetwork(); + + Ipv4GlobalRoutingHelper::PopulateRoutingTables(); + + // Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", + // QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, + // projected_queue_max_packets))); + Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", + QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, 1))); + + TrafficControlHelper tch; + tch.SetRootQueueDisc("ns3::PfifoFastQueueDisc"); + QueueDiscContainer qd; + tch.Uninstall(routers.Get(0)->GetDevice(0)); + qd.Add(tch.Install(routers.Get(0)->GetDevice(0)).Get(0)); + + /* Trace the QueueDisc Queue size */ + if (storeTraces == false) { + Ptr q = qd.Get(0); + q->TraceConnectWithoutContext("PacketsInQueue", + MakeCallback(&PacketsInQueueDisc)); } - }); - // Stop sending packets after the specified duration - Simulator::Schedule(startDelay + duration, &Socket::Close, socket); -} + /* Trace the DropTail Queue size */ + if (storeTraces) { + Ptr nd = routers.Get(0)->GetDevice(0); + Ptr ptpnd = + DynamicCast(nd); + Ptr> queue = ptpnd->GetQueue(); + queue->TraceConnectWithoutContext("PacketsInQueue", + MakeCallback(&PacketsInDroptail)); + } + + /* Trace packets dropped by the QueueDisc Queue */ + if (storeTraces) { + AsciiTraceHelper ascii; + Ptr streamWrapper; + streamWrapper = + ascii.CreateFileStream(tracesPath + "droppedQueueDisc.txt"); + qd.Get(0)->TraceConnectWithoutContext( + "Drop", MakeBoundCallback(&DropAtQueue, streamWrapper)); + } + + netDeviceToDropPacket = &r1r2ND; + /* Callback to the ExaminePacket */ + r1r2ND.Get(0)->TraceConnectWithoutContext("MacTx", + MakeCallback(&ExaminePacket)); + + /* Packet Printing is mandatory for the Packet Drop Test */ + Packet::EnablePrinting(); + + uint16_t server_port = 50000; + /* Install packet sink at receiver side */ + InstallPacketSink(rightNodes.Get(0), server_port, socketFactory, + Seconds(0.01), stopTimeSimulation); + // InstallPacketSink(rightNodes.Get(0), server_port, + // "ns3::UdpSocketFactory", + // Seconds(0.01), stopTimeSimulation); + + /* Install BulkSend application */ + // InstallBulkSend(leftNodes.Get(0), routerToRightIPAddress.GetAddress(1), + // server_port, socketFactory, 2, 0, + // MakeCallback(&CwndChange), bytes_to_send, Seconds(0.2)); + + // Congestion PARAMETERS + uint16_t serverPort = 50000; + Time startDelay = Seconds(1.0); + Time duration = Seconds(5.0); + uint32_t numPackets = 512; + uint32_t packetSize = 1024; + Time interval = MilliSeconds(10); + Ipv4Address receiverAddress = routerToRightIPAddress.GetAddress(1); + + // Schedule the congestion + // Simulator::Schedule(startDelay, [congestionNode, startDelay, duration, + // numPackets, packetSize, interval, + // receiverAddress, serverPort]() { + // Ptr node = congestionNode.Get(0); + // // double startDelaySeconds = startDelay.GetSeconds(); + // // double duration + // SimulateCongestion(node, startDelay, duration, numPackets, + // packetSize, + // interval, receiverAddress, serverPort); + // }); + + // SimulateCongestion(congestionNode.Get(0), startDelay, duration, + // numPackets, + // packetSize, interval, receiverAddress, serverPort); + + OnOffHelper onoff( + "ns3::UdpSocketFactory", + InetSocketAddress(routerToRightIPAddress.GetAddress(1), 50000)); + onoff.SetAttribute("PacketSize", UintegerValue(8)); + onoff.SetAttribute("DataRate", DataRateValue(DataRate("1kbps"))); + + ApplicationContainer app = onoff.Install(congestionNode.Get(0)); + app.Start(Seconds(1.0)); + app.Stop(Seconds(3.0)); + + if (storeTraces) { + pointToPointLeaf.EnablePcapAll(tracesPath); + } -int main(int argc, char *argv[]) { - // Command line arguments - CommandLine cmd; - cmd.AddValue("tcpVariantId", "TCP variant", tcpVariantId); - cmd.AddValue("enableSack", "Enable/disable sack in TCP", enableSack); - cmd.AddValue("seed", "The random seed", seed); - cmd.AddValue("simStopTime", "The simulation stop time", stopTimeSimulation); - cmd.AddValue("intervalTCP", "The TCP interval", intervalTCP); - cmd.AddValue("initialCwnd", "Initial CWND window", initialCwnd); - cmd.AddValue("bytesToSend", "Number of bytes to send", bytes_to_send); - cmd.Parse(argc, argv); - - // Set Random Seed - Random::seed(seed); - - // TCP Recovery Algorithm - Config::SetDefault("ns3::TcpL4Protocol::RecoveryType", - TypeIdValue(TypeId::LookupByName(tcpRecovery))); - - // Set Congestion Control Algorithm - Config::SetDefault("ns3::TcpL4Protocol::SocketType", - StringValue(tcpVariantId)); - Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(1073741824)); - Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(1073741824)); - - // Set default initial congestion window - Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(initialCwnd)); - - // Set default delayed ack count to a specified value - Config::SetDefault("ns3::TcpSocket::DelAckTimeout", - TimeValue(Time(delAckTimeout))); - Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(delAckCount)); - // Config::SetDefault("ns3::TcpSocket::SetTcpNoDelay", BooleanValue(true)); - - // Set default segment size of TCP packet to a specified value - Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(segmentSize)); - - // Enable/Disable SACK in TCP - Config::SetDefault("ns3::TcpSocketBase::Sack", BooleanValue(enableSack)); - - Config::SetDefault("ns3::TcpSocketBase::MinRto", TimeValue(Seconds(minRTO))); - - NodeContainer leftNodes, rightNodes, routers; - routers.Create(2); - leftNodes.Create(1); - rightNodes.Create(1); - - Names::Add("Router1", routers.Get(0)); - Names::Add("Router2", routers.Get(1)); - Names::Add("Sender", leftNodes.Get(0)); - Names::Add("Receiver", rightNodes.Get(0)); - - // Congestion node setup - NodeContainer congestionNode; - congestionNode.Create(1); - Names::Add("CongestionSender", congestionNode.Get(0)); - - DataRate b_access(bandwidth_access); - DataRate b_bottleneck(bandwidth_bottleneck); - Time d_access(delay_access); - Time d_bottleneck(delay_bottleneck); - Time d_serialization(delay_serialization); - - uint32_t max_bottleneck_bytes = static_cast( - ((std::min(b_access, b_bottleneck).GetBitRate() / 8) * - (((d_access * 2) + d_bottleneck) * 2 + d_serialization).GetSeconds())); - uint32_t projected_queue_max_packets = - std::ceil(max_bottleneck_bytes / MTU_bytes); - - // Set Droptail queue size to 1 packet - Config::SetDefault("ns3::DropTailQueue::MaxSize", StringValue("1p")); - - // Create the point-to-point link helpers and connect two router nodes - PointToPointHelper pointToPointRouter; - pointToPointRouter.SetDeviceAttribute("DataRate", - StringValue(bandwidth_bottleneck)); - pointToPointRouter.SetChannelAttribute("Delay", - StringValue(delay_bottleneck)); - - NetDeviceContainer r1r2ND = - pointToPointRouter.Install(routers.Get(0), routers.Get(1)); - - // Create the point-to-point link helpers and connect leaf nodes to router - PointToPointHelper pointToPointLeaf; - pointToPointLeaf.SetDeviceAttribute("DataRate", - StringValue(bandwidth_access)); - pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); - - NetDeviceContainer leftToRouter = - pointToPointLeaf.Install(leftNodes.Get(0), routers.Get(0)); - NetDeviceContainer routerToRight = - pointToPointLeaf.Install(routers.Get(1), rightNodes.Get(0)); - - // Link CongestioNSender to Router1 - NetDeviceContainer congestionSenderToRouter = - pointToPointLeaf.Install(congestionNode.Get(0), routers.Get(0)); - - InternetStackHelper internetStack; - internetStack.Install(leftNodes); - internetStack.Install(rightNodes); - internetStack.Install(routers); - internetStack.Install(congestionNode); - - Ipv4AddressHelper ipAddresses("10.0.0.0", "255.255.255.0"); - Ipv4InterfaceContainer r1r2IPAddress = ipAddresses.Assign(r1r2ND); - ipAddresses.NewNetwork(); - Ipv4InterfaceContainer leftToRouterIPAddress = - ipAddresses.Assign(leftToRouter); - ipAddresses.NewNetwork(); - Ipv4InterfaceContainer routerToRightIPAddress = - ipAddresses.Assign(routerToRight); - ipAddresses.NewNetwork(); - Ipv4InterfaceContainer congestionToRouter0IPAddress = - ipAddresses.Assign(congestionSenderToRouter); - ipAddresses.NewNetwork(); - - Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - - // Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", - // QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, - // projected_queue_max_packets))); - Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", - QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, 1))); - - TrafficControlHelper tch; - tch.SetRootQueueDisc("ns3::PfifoFastQueueDisc"); - QueueDiscContainer qd; - tch.Uninstall(routers.Get(0)->GetDevice(0)); - qd.Add(tch.Install(routers.Get(0)->GetDevice(0)).Get(0)); - - /* Trace the QueueDisc Queue size */ - if (storeTraces == false) { - Ptr q = qd.Get(0); - q->TraceConnectWithoutContext("PacketsInQueue", - MakeCallback(&PacketsInQueueDisc)); - } - - /* Trace the DropTail Queue size */ - if (storeTraces) { - Ptr nd = routers.Get(0)->GetDevice(0); - Ptr ptpnd = DynamicCast(nd); - Ptr> queue = ptpnd->GetQueue(); - queue->TraceConnectWithoutContext("PacketsInQueue", - MakeCallback(&PacketsInDroptail)); - } - - /* Trace packets dropped by the QueueDisc Queue */ - if (storeTraces) { - AsciiTraceHelper ascii; - Ptr streamWrapper; - streamWrapper = ascii.CreateFileStream(tracesPath + "droppedQueueDisc.txt"); - qd.Get(0)->TraceConnectWithoutContext( - "Drop", MakeBoundCallback(&DropAtQueue, streamWrapper)); - } - - netDeviceToDropPacket = &r1r2ND; - /* Callback to the ExaminePacket */ - r1r2ND.Get(0)->TraceConnectWithoutContext("MacTx", - MakeCallback(&ExaminePacket)); - - /* Packet Printing is mandatory for the Packet Drop Test */ - Packet::EnablePrinting(); - - uint16_t server_port = 50000; - /* Install packet sink at receiver side */ - InstallPacketSink(rightNodes.Get(0), server_port, socketFactory, - Seconds(0.01), stopTimeSimulation); - // InstallPacketSink(rightNodes.Get(0), server_port, "ns3::UdpSocketFactory", - // Seconds(0.01), stopTimeSimulation); - - /* Install BulkSend application */ - // InstallBulkSend(leftNodes.Get(0), routerToRightIPAddress.GetAddress(1), - // server_port, socketFactory, 2, 0, - // MakeCallback(&CwndChange), bytes_to_send, Seconds(0.2)); - - // Congestion PARAMETERS - uint16_t serverPort = 50000; - Time startDelay = Seconds(1.0); - Time duration = Seconds(5.0); - uint32_t numPackets = 512; - uint32_t packetSize = 1024; - Time interval = MilliSeconds(10); - Ipv4Address receiverAddress = routerToRightIPAddress.GetAddress(1); - - // Schedule the congestion - // Simulator::Schedule(startDelay, [congestionNode, startDelay, duration, - // numPackets, packetSize, interval, - // receiverAddress, serverPort]() { - // Ptr node = congestionNode.Get(0); - // // double startDelaySeconds = startDelay.GetSeconds(); - // // double duration - // SimulateCongestion(node, startDelay, duration, numPackets, packetSize, - // interval, receiverAddress, serverPort); - // }); - - // SimulateCongestion(congestionNode.Get(0), startDelay, duration, numPackets, - // packetSize, interval, receiverAddress, serverPort); - - OnOffHelper onoff( - "ns3::UdpSocketFactory", - InetSocketAddress(routerToRightIPAddress.GetAddress(1), 50000)); - onoff.SetAttribute("PacketSize", UintegerValue(8)); - onoff.SetAttribute("DataRate", DataRateValue(DataRate("1kbps"))); - - ApplicationContainer app = onoff.Install(congestionNode.Get(0)); - app.Start(Seconds(1.0)); - app.Stop(Seconds(3.0)); - - if (storeTraces) { - pointToPointLeaf.EnablePcapAll(tracesPath); - } - - // Simulator::Stop(stopTimeSimulation); - Simulator::Run(); - Simulator::Destroy(); - return 0; + // Simulator::Stop(stopTimeSimulation); + Simulator::Run(); + Simulator::Destroy(); + return 0; } From 8e1b61f6320c51fbe03f71d2ce66c2f4b0bc1bc8 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Sat, 9 Mar 2024 19:16:33 +0000 Subject: [PATCH 09/28] :art: format files --- libs/basic_congestion.h | 15 +- libs/frr_queue.h | 31 +- libs/modulo_congestion_policy.h | 1 - src/basic_congestion.cc | 551 ++++++++++++++++---------------- 4 files changed, 302 insertions(+), 296 deletions(-) diff --git a/libs/basic_congestion.h b/libs/basic_congestion.h index b3a0beef..1e2a09d2 100644 --- a/libs/basic_congestion.h +++ b/libs/basic_congestion.h @@ -1,15 +1,14 @@ #ifndef BASIC_CONGESTION_POLICY_H #define BASIC_CONGESTION_POLICY_H - namespace ns3 { - template class BasicCongestionPolicy { - static_assert(MAX_USAGE_PERCENTAGE > 0 && MAX_USAGE_PERCENTAGE <= 100, "MAX_USAGE_PERCENTAGE must be between 1 and 100"); + static_assert(MAX_USAGE_PERCENTAGE > 0 && MAX_USAGE_PERCENTAGE <= 100, + "MAX_USAGE_PERCENTAGE must be between 1 and 100"); public: static bool isCongested(ns3::Queue* queue); @@ -18,17 +17,17 @@ class BasicCongestionPolicy template <> bool BasicCongestionPolicy<100>::isCongested(ns3::Queue* queue) { - return queue->GetNPackets() >= queue->GetMaxSize().GetValue(); + return queue->GetNPackets() >= queue->GetMaxSize().GetValue(); } template -bool BasicCongestionPolicy::isCongested(ns3::Queue* queue) +bool BasicCongestionPolicy::isCongested( + ns3::Queue* queue) { - return queue->GetNPackets() * 100 >= queue->GetMaxSize().GetValue() * MAX_USAGE_PERCENTAGE; + return queue->GetNPackets() * 100 >= + queue->GetMaxSize().GetValue() * MAX_USAGE_PERCENTAGE; } - - } // namespace ns3 #endif diff --git a/libs/frr_queue.h b/libs/frr_queue.h index d3084491..3ed72a83 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -27,7 +27,7 @@ class FRRQueue : public Queue using Queue::DoDequeue; using Queue::DoRemove; using Queue::DoPeek; - + int m_uid; NS_LOG_TEMPLATE_DECLARE; @@ -41,7 +41,7 @@ class FRRQueue : public Queue virtual Ptr Peek() const override; public: - static int s_uid; + static int s_uid; FRR_POLICY m_frrPolicy; CONGESTION_POLICY m_congestionPolicy; @@ -58,12 +58,9 @@ class FRRQueue : public Queue template int FRRQueue::s_uid = 0; - template FRRQueue::FRRQueue() - : Queue(), - m_uid(s_uid++), - NS_LOG_TEMPLATE_DEFINE("FRRQueue") + : Queue(), m_uid(s_uid++), NS_LOG_TEMPLATE_DEFINE("FRRQueue") { NS_LOG_FUNCTION(this); } @@ -71,7 +68,7 @@ FRRQueue::FRRQueue() template FRRQueue::~FRRQueue() { - //NS_LOG_FUNCTION(this); + // NS_LOG_FUNCTION(this); } template @@ -94,16 +91,18 @@ template bool FRRQueue::Enqueue(Ptr packet) { NS_LOG_FUNCTION(this << packet); - if (m_congestionPolicy.isCongested(this)) - { - NS_LOG_LOGIC("(" << m_uid << ") Congested Route, Rerouting packet: " << packet); + if (m_congestionPolicy.isCongested(this)) { + NS_LOG_LOGIC("(" << m_uid + << ") Congested Route, Rerouting packet: " << packet); ForwardToAlternateTarget(packet); NS_LOG_LOGIC("(" << m_uid << ") Rerouting complete"); - return false; + return false; } - NS_LOG_LOGIC("(" << m_uid << ") Enqueued " << packet << " to " << GetNPackets() << " packets in queue."); + NS_LOG_LOGIC("(" << m_uid << ") Enqueued " << packet << " to " + << GetNPackets() << " packets in queue."); DoEnqueue(GetContainer().end(), packet); - NS_LOG_LOGIC("(" << m_uid << ") Enqueued " << packet << " to " << GetNPackets() << " packets in queue."); + NS_LOG_LOGIC("(" << m_uid << ") Enqueued " << packet << " to " + << GetNPackets() << " packets in queue."); return true; } @@ -142,8 +141,10 @@ template void FRRQueue::ForwardToAlternateTarget( Ptr packet) { - Ptr alternativeTarget = m_frrPolicy.selectAlternativeTarget(); - if (alternativeTarget) alternativeTarget->Send(packet, alternativeTarget->GetAddress(), 0x0800); + Ptr alternativeTarget = m_frrPolicy.selectAlternativeTarget(); + if (alternativeTarget) + alternativeTarget->Send(packet, alternativeTarget->GetAddress(), + 0x0800); } template diff --git a/libs/modulo_congestion_policy.h b/libs/modulo_congestion_policy.h index 6b970062..0bb5d15b 100644 --- a/libs/modulo_congestion_policy.h +++ b/libs/modulo_congestion_policy.h @@ -9,7 +9,6 @@ class ModuloCongestionPolicy int counter; public: - bool isCongested(ns3::Queue* queue) { increment(); diff --git a/src/basic_congestion.cc b/src/basic_congestion.cc index 50ac057e..0c6f23bc 100644 --- a/src/basic_congestion.cc +++ b/src/basic_congestion.cc @@ -19,7 +19,6 @@ #include "../libs/frr_queue.h" #include "../libs/lfa_policy.h" - using namespace ns3; using Random = effolkronium::random_static; @@ -35,24 +34,24 @@ NS_OBJECT_ENSURE_REGISTERED(SimulationQueue); // ---------------------------------------------------- // template -Ptr getDevice(const NetDeviceContainer& devices) +Ptr getDevice(const NetDeviceContainer& devices) { return devices.Get(INDEX)->GetObject(); } template -Ptr getQueue(const NetDeviceContainer& devices) +Ptr getQueue(const NetDeviceContainer& devices) { return DynamicCast(getDevice(devices)->GetQueue()); } template -void setAlternateTarget(const NetDeviceContainer& devices, Ptr target) +void setAlternateTarget(const NetDeviceContainer& devices, + Ptr target) { getQueue(devices)->addAlternateTargets(target); } - // Random Seed uint32_t seed = 1; @@ -77,8 +76,8 @@ Time stopTimeSimulation = Seconds(5000); Time intervalTCP = Seconds(1); // ---[TCP PARAMETERS] --- -uint32_t segmentSize = 32; //1024; -uint32_t MTU_bytes = 38;// segmentSize + 54; +uint32_t segmentSize = 32; // 1024; +uint32_t MTU_bytes = 38; // segmentSize + 54; uint8_t delAckCount = 1; uint8_t initialCwnd = 1; // std::string delAckTimeout = "200ms"; @@ -101,7 +100,6 @@ std::string delay_serialization = "1.9ms"; // ---[POINTER TO THE DEVICE THAT WILL IMPLEMENT PACKET DROPING] NetDeviceContainer* netDeviceToDropPacket = NULL; - // -------------------------------------------------- // // --- END OF SIMULATION CONFIGURATION PARAMETERS --- // // -------------------------------------------------- // @@ -225,271 +223,280 @@ void ExaminePacket(Ptr packet) void SimulateCongestion(Ptr congestionNode, Time startDelay, Time duration, unsigned int numPackets, unsigned int packetSize, Time interval, - Ipv4Address receiverAddress, uint16_t port) { - // Create a UDP socket - Ptr socket = - Socket::CreateSocket(congestionNode, UdpSocketFactory::GetTypeId()); - InetSocketAddress receiverSocketAddress(receiverAddress, port); - - // Schedule sending packets using the UDP socket - Simulator::Schedule(startDelay, [socket, receiverSocketAddress, numPackets, - packetSize, interval]() { - for (unsigned int i = 0; i < numPackets; ++i) { - // std::cout << "sending packet " << i << std::endl; - Ptr packet = Create(packetSize); - int err = socket->SendTo(packet, packetSize, receiverSocketAddress); - if (err == -1) { - std::cout << "error sending packet " << i << std::endl; - } + Ipv4Address receiverAddress, uint16_t port) +{ + // Create a UDP socket + Ptr socket = + Socket::CreateSocket(congestionNode, UdpSocketFactory::GetTypeId()); + InetSocketAddress receiverSocketAddress(receiverAddress, port); + + // Schedule sending packets using the UDP socket + Simulator::Schedule(startDelay, [socket, receiverSocketAddress, numPackets, + packetSize, interval]() { + for (unsigned int i = 0; i < numPackets; ++i) { + // std::cout << "sending packet " << i << std::endl; + Ptr packet = Create(packetSize); + int err = socket->SendTo(packet, packetSize, receiverSocketAddress); + if (err == -1) { + std::cout << "error sending packet " << i << std::endl; + } + } + }); + + // Stop sending packets after the specified duration + Simulator::Schedule(startDelay + duration, &Socket::Close, socket); +} + +int main(int argc, char* argv[]) +{ + LogComponentEnable("FRRQueue", LOG_LEVEL_LOGIC); + NS_LOG_INFO("Creating Topology"); + // Command line arguments + CommandLine cmd; + cmd.AddValue("tcpVariantId", "TCP variant", tcpVariantId); + cmd.AddValue("enableSack", "Enable/disable sack in TCP", enableSack); + cmd.AddValue("seed", "The random seed", seed); + cmd.AddValue("simStopTime", "The simulation stop time", stopTimeSimulation); + cmd.AddValue("intervalTCP", "The TCP interval", intervalTCP); + cmd.AddValue("initialCwnd", "Initial CWND window", initialCwnd); + cmd.AddValue("bytesToSend", "Number of bytes to send", bytes_to_send); + cmd.Parse(argc, argv); + + // Set Random Seed + Random::seed(seed); + + // TCP Recovery Algorithm + Config::SetDefault("ns3::TcpL4Protocol::RecoveryType", + TypeIdValue(TypeId::LookupByName(tcpRecovery))); + + // Set Congestion Control Algorithm + Config::SetDefault("ns3::TcpL4Protocol::SocketType", + StringValue(tcpVariantId)); + Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(1073741824)); + Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(1073741824)); + + // Set default initial congestion window + Config::SetDefault("ns3::TcpSocket::InitialCwnd", + UintegerValue(initialCwnd)); + + // Set default delayed ack count to a specified value + Config::SetDefault("ns3::TcpSocket::DelAckTimeout", + TimeValue(Time(delAckTimeout))); + Config::SetDefault("ns3::TcpSocket::DelAckCount", + UintegerValue(delAckCount)); + // Config::SetDefault("ns3::TcpSocket::SetTcpNoDelay", BooleanValue(true)); + + // Set default segment size of TCP packet to a specified value + Config::SetDefault("ns3::TcpSocket::SegmentSize", + UintegerValue(segmentSize)); + + // Enable/Disable SACK in TCP + Config::SetDefault("ns3::TcpSocketBase::Sack", BooleanValue(enableSack)); + + Config::SetDefault("ns3::TcpSocketBase::MinRto", + TimeValue(Seconds(minRTO))); + + NodeContainer leftNodes, rightNodes, routers; + routers.Create(3); + leftNodes.Create(1); + rightNodes.Create(1); + + Names::Add("Router1", routers.Get(0)); + Names::Add("Router2", routers.Get(1)); + Names::Add("Router3", routers.Get(2)); + Names::Add("Sender", leftNodes.Get(0)); + Names::Add("Receiver", rightNodes.Get(0)); + + // Congestion node setup + NodeContainer congestionNode; + congestionNode.Create(1); + Names::Add("CongestionSender", congestionNode.Get(0)); + + DataRate b_access(bandwidth_access); + DataRate b_bottleneck(bandwidth_bottleneck); + Time d_access(delay_access); + Time d_bottleneck(delay_bottleneck); + Time d_serialization(delay_serialization); + + uint32_t max_bottleneck_bytes = static_cast( + ((std::min(b_access, b_bottleneck).GetBitRate() / 8) * + (((d_access * 2) + d_bottleneck) * 2 + d_serialization).GetSeconds())); + uint32_t projected_queue_max_packets = + std::ceil(max_bottleneck_bytes / MTU_bytes); + + // Set Droptail queue size to 1 packet + Config::SetDefault(SimulationQueue::getQueueString() + "::MaxSize", + StringValue("100p")); + + // Create the point-to-point link helpers and connect two router nodes + PointToPointHelper pointToPointRouter; + pointToPointRouter.SetQueue(SimulationQueue::getQueueString()); + pointToPointRouter.SetDeviceAttribute("DataRate", + StringValue(bandwidth_bottleneck)); + pointToPointRouter.SetChannelAttribute("Delay", + StringValue(delay_bottleneck)); + + // Draw a ring topology between R1 -> R2 -> R3 + /* + * R3 + * / \ + * / \ + * CS --- R1----R2 --- R + */ + NetDeviceContainer r1r2ND = + pointToPointRouter.Install(routers.Get(0), routers.Get(1)); + + NetDeviceContainer r1r3ND = + pointToPointRouter.Install(routers.Get(0), routers.Get(2)); + NetDeviceContainer r3r2ND = + pointToPointRouter.Install(routers.Get(2), routers.Get(1)); + + setAlternateTarget<0>(r1r2ND, getDevice<0>(r1r3ND)); + // setAlternateTarget<0>(r1r2ND, getDevice<0>(devices02)); + + // Create the point-to-point link helpers and connect leaf nodes to router + PointToPointHelper pointToPointLeaf; + // pointToPointLeaf.SetQueue(SimulationQueue::getQueueString()); + pointToPointLeaf.SetDeviceAttribute("DataRate", + StringValue(bandwidth_access)); + pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); + + NetDeviceContainer leftToRouter = + pointToPointLeaf.Install(leftNodes.Get(0), routers.Get(0)); + NetDeviceContainer routerToRight = + pointToPointLeaf.Install(routers.Get(1), rightNodes.Get(0)); + + // Link CongestioNSender to Router1 + NetDeviceContainer congestionSenderToRouter = + pointToPointLeaf.Install(congestionNode.Get(0), routers.Get(0)); + + InternetStackHelper internetStack; + internetStack.Install(leftNodes); + internetStack.Install(rightNodes); + internetStack.Install(routers); + internetStack.Install(congestionNode); + + Ipv4AddressHelper ipAddresses("10.0.0.0", "255.255.255.0"); + Ipv4InterfaceContainer r1r2IPAddress = ipAddresses.Assign(r1r2ND); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer leftToRouterIPAddress = + ipAddresses.Assign(leftToRouter); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer routerToRightIPAddress = + ipAddresses.Assign(routerToRight); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer congestionToRouter0IPAddress = + ipAddresses.Assign(congestionSenderToRouter); + ipAddresses.NewNetwork(); + + Ipv4InterfaceContainer r1r3IPAddress = ipAddresses.Assign(r1r3ND); + ipAddresses.NewNetwork(); + Ipv4InterfaceContainer r3r2IPAddress = ipAddresses.Assign(r3r2ND); + ipAddresses.NewNetwork(); + + Ipv4GlobalRoutingHelper::PopulateRoutingTables(); + + // Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", + // QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, + // projected_queue_max_packets))); + Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", + QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, 100))); + + TrafficControlHelper tch; + tch.SetRootQueueDisc("ns3::PfifoFastQueueDisc"); + QueueDiscContainer qd; + tch.Uninstall(routers.Get(0)->GetDevice(0)); + qd.Add(tch.Install(routers.Get(0)->GetDevice(0)).Get(0)); + + /* Trace the QueueDisc Queue size */ + if (storeTraces == false) { + Ptr q = qd.Get(0); + q->TraceConnectWithoutContext("PacketsInQueue", + MakeCallback(&PacketsInQueueDisc)); } - }); - // Stop sending packets after the specified duration - Simulator::Schedule(startDelay + duration, &Socket::Close, socket); -} + /* Trace the DropTail Queue size */ + if (storeTraces) { + Ptr nd = routers.Get(0)->GetDevice(0); + Ptr ptpnd = + DynamicCast(nd); + Ptr> queue = ptpnd->GetQueue(); + queue->TraceConnectWithoutContext("PacketsInQueue", + MakeCallback(&PacketsInDroptail)); + } + + /* Trace packets dropped by the QueueDisc Queue */ + if (storeTraces) { + AsciiTraceHelper ascii; + Ptr streamWrapper; + streamWrapper = + ascii.CreateFileStream(tracesPath + "droppedQueueDisc.txt"); + qd.Get(0)->TraceConnectWithoutContext( + "Drop", MakeBoundCallback(&DropAtQueue, streamWrapper)); + } + + netDeviceToDropPacket = &r1r2ND; + /* Callback to the ExaminePacket */ + r1r2ND.Get(0)->TraceConnectWithoutContext("MacTx", + MakeCallback(&ExaminePacket)); + + /* Packet Printing is mandatory for the Packet Drop Test */ + Packet::EnablePrinting(); + + uint16_t server_port = 50000; + /* Install packet sink at receiver side */ + InstallPacketSink(rightNodes.Get(0), server_port, socketFactory, + Seconds(0.01), stopTimeSimulation); + // InstallPacketSink(rightNodes.Get(0), server_port, + // "ns3::UdpSocketFactory", + // Seconds(0.01), stopTimeSimulation); + + /* Install BulkSend application */ + // InstallBulkSend(leftNodes.Get(0), routerToRightIPAddress.GetAddress(1), + // server_port, socketFactory, 2, 0, + // MakeCallback(&CwndChange), bytes_to_send, Seconds(0.2)); + + // Congestion PARAMETERS + uint16_t serverPort = 50000; + Time startDelay = Seconds(1.0); + Time duration = Seconds(5.0); + uint32_t numPackets = 512; + uint32_t packetSize = 1024; + Time interval = MilliSeconds(10); + Ipv4Address receiverAddress = routerToRightIPAddress.GetAddress(1); + + // Schedule the congestion + // Simulator::Schedule(startDelay, [congestionNode, startDelay, duration, + // numPackets, packetSize, interval, + // receiverAddress, serverPort]() { + // Ptr node = congestionNode.Get(0); + // // double startDelaySeconds = startDelay.GetSeconds(); + // // double duration + // SimulateCongestion(node, startDelay, duration, numPackets, + // packetSize, + // interval, receiverAddress, serverPort); + // }); + + // SimulateCongestion(congestionNode.Get(0), startDelay, duration, + // numPackets, + // packetSize, interval, receiverAddress, serverPort); + + OnOffHelper onoff( + "ns3::UdpSocketFactory", + InetSocketAddress(routerToRightIPAddress.GetAddress(1), 50000)); + onoff.SetAttribute("PacketSize", UintegerValue(8)); + onoff.SetAttribute("DataRate", DataRateValue(DataRate("200kbps"))); + + ApplicationContainer app = onoff.Install(congestionNode.Get(0)); + app.Start(Seconds(1.0)); + app.Stop(Seconds(3.0)); + + if (storeTraces) { + pointToPointRouter.EnablePcapAll(tracesPath); + } -int main(int argc, char *argv[]) { - LogComponentEnable("FRRQueue", LOG_LEVEL_LOGIC); - NS_LOG_INFO("Creating Topology"); - // Command line arguments - CommandLine cmd; - cmd.AddValue("tcpVariantId", "TCP variant", tcpVariantId); - cmd.AddValue("enableSack", "Enable/disable sack in TCP", enableSack); - cmd.AddValue("seed", "The random seed", seed); - cmd.AddValue("simStopTime", "The simulation stop time", stopTimeSimulation); - cmd.AddValue("intervalTCP", "The TCP interval", intervalTCP); - cmd.AddValue("initialCwnd", "Initial CWND window", initialCwnd); - cmd.AddValue("bytesToSend", "Number of bytes to send", bytes_to_send); - cmd.Parse(argc, argv); - - // Set Random Seed - Random::seed(seed); - - // TCP Recovery Algorithm - Config::SetDefault("ns3::TcpL4Protocol::RecoveryType", - TypeIdValue(TypeId::LookupByName(tcpRecovery))); - - // Set Congestion Control Algorithm - Config::SetDefault("ns3::TcpL4Protocol::SocketType", - StringValue(tcpVariantId)); - Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(1073741824)); - Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(1073741824)); - - // Set default initial congestion window - Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(initialCwnd)); - - // Set default delayed ack count to a specified value - Config::SetDefault("ns3::TcpSocket::DelAckTimeout", - TimeValue(Time(delAckTimeout))); - Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(delAckCount)); - // Config::SetDefault("ns3::TcpSocket::SetTcpNoDelay", BooleanValue(true)); - - // Set default segment size of TCP packet to a specified value - Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(segmentSize)); - - // Enable/Disable SACK in TCP - Config::SetDefault("ns3::TcpSocketBase::Sack", BooleanValue(enableSack)); - - Config::SetDefault("ns3::TcpSocketBase::MinRto", TimeValue(Seconds(minRTO))); - - NodeContainer leftNodes, rightNodes, routers; - routers.Create(3); - leftNodes.Create(1); - rightNodes.Create(1); - - Names::Add("Router1", routers.Get(0)); - Names::Add("Router2", routers.Get(1)); - Names::Add("Router3", routers.Get(2)); - Names::Add("Sender", leftNodes.Get(0)); - Names::Add("Receiver", rightNodes.Get(0)); - - // Congestion node setup - NodeContainer congestionNode; - congestionNode.Create(1); - Names::Add("CongestionSender", congestionNode.Get(0)); - - DataRate b_access(bandwidth_access); - DataRate b_bottleneck(bandwidth_bottleneck); - Time d_access(delay_access); - Time d_bottleneck(delay_bottleneck); - Time d_serialization(delay_serialization); - - uint32_t max_bottleneck_bytes = static_cast( - ((std::min(b_access, b_bottleneck).GetBitRate() / 8) * - (((d_access * 2) + d_bottleneck) * 2 + d_serialization).GetSeconds())); - uint32_t projected_queue_max_packets = - std::ceil(max_bottleneck_bytes / MTU_bytes); - - // Set Droptail queue size to 1 packet - Config::SetDefault(SimulationQueue::getQueueString() + "::MaxSize", StringValue("100p")); - - // Create the point-to-point link helpers and connect two router nodes - PointToPointHelper pointToPointRouter; - pointToPointRouter.SetQueue(SimulationQueue::getQueueString()); - pointToPointRouter.SetDeviceAttribute("DataRate", - StringValue(bandwidth_bottleneck)); - pointToPointRouter.SetChannelAttribute("Delay", - StringValue(delay_bottleneck)); - - - - // Draw a ring topology between R1 -> R2 -> R3 - /* - * R3 - * / \ - * / \ - * CS --- R1----R2 --- R - */ - NetDeviceContainer r1r2ND = - pointToPointRouter.Install(routers.Get(0), routers.Get(1)); - - NetDeviceContainer r1r3ND = - pointToPointRouter.Install(routers.Get(0), routers.Get(2)); - NetDeviceContainer r3r2ND = - pointToPointRouter.Install(routers.Get(2), routers.Get(1)); - - setAlternateTarget<0>(r1r2ND, getDevice<0>(r1r3ND)); - //setAlternateTarget<0>(r1r2ND, getDevice<0>(devices02)); - - // Create the point-to-point link helpers and connect leaf nodes to router - PointToPointHelper pointToPointLeaf; - //pointToPointLeaf.SetQueue(SimulationQueue::getQueueString()); - pointToPointLeaf.SetDeviceAttribute("DataRate", - StringValue(bandwidth_access)); - pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); - - NetDeviceContainer leftToRouter = - pointToPointLeaf.Install(leftNodes.Get(0), routers.Get(0)); - NetDeviceContainer routerToRight = - pointToPointLeaf.Install(routers.Get(1), rightNodes.Get(0)); - - // Link CongestioNSender to Router1 - NetDeviceContainer congestionSenderToRouter = - pointToPointLeaf.Install(congestionNode.Get(0), routers.Get(0)); - - InternetStackHelper internetStack; - internetStack.Install(leftNodes); - internetStack.Install(rightNodes); - internetStack.Install(routers); - internetStack.Install(congestionNode); - - Ipv4AddressHelper ipAddresses("10.0.0.0", "255.255.255.0"); - Ipv4InterfaceContainer r1r2IPAddress = ipAddresses.Assign(r1r2ND); - ipAddresses.NewNetwork(); - Ipv4InterfaceContainer leftToRouterIPAddress = - ipAddresses.Assign(leftToRouter); - ipAddresses.NewNetwork(); - Ipv4InterfaceContainer routerToRightIPAddress = - ipAddresses.Assign(routerToRight); - ipAddresses.NewNetwork(); - Ipv4InterfaceContainer congestionToRouter0IPAddress = - ipAddresses.Assign(congestionSenderToRouter); - ipAddresses.NewNetwork(); - - - Ipv4InterfaceContainer r1r3IPAddress = ipAddresses.Assign(r1r3ND); - ipAddresses.NewNetwork(); - Ipv4InterfaceContainer r3r2IPAddress = ipAddresses.Assign(r3r2ND); - ipAddresses.NewNetwork(); - - Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - - // Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", - // QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, - // projected_queue_max_packets))); - Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", - QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, 100))); - - TrafficControlHelper tch; - tch.SetRootQueueDisc("ns3::PfifoFastQueueDisc"); - QueueDiscContainer qd; - tch.Uninstall(routers.Get(0)->GetDevice(0)); - qd.Add(tch.Install(routers.Get(0)->GetDevice(0)).Get(0)); - - /* Trace the QueueDisc Queue size */ - if (storeTraces == false) { - Ptr q = qd.Get(0); - q->TraceConnectWithoutContext("PacketsInQueue", - MakeCallback(&PacketsInQueueDisc)); - } - - /* Trace the DropTail Queue size */ - if (storeTraces) { - Ptr nd = routers.Get(0)->GetDevice(0); - Ptr ptpnd = DynamicCast(nd); - Ptr> queue = ptpnd->GetQueue(); - queue->TraceConnectWithoutContext("PacketsInQueue", - MakeCallback(&PacketsInDroptail)); - } - - /* Trace packets dropped by the QueueDisc Queue */ - if (storeTraces) { - AsciiTraceHelper ascii; - Ptr streamWrapper; - streamWrapper = ascii.CreateFileStream(tracesPath + "droppedQueueDisc.txt"); - qd.Get(0)->TraceConnectWithoutContext( - "Drop", MakeBoundCallback(&DropAtQueue, streamWrapper)); - } - - netDeviceToDropPacket = &r1r2ND; - /* Callback to the ExaminePacket */ - r1r2ND.Get(0)->TraceConnectWithoutContext("MacTx", - MakeCallback(&ExaminePacket)); - - /* Packet Printing is mandatory for the Packet Drop Test */ - Packet::EnablePrinting(); - - uint16_t server_port = 50000; - /* Install packet sink at receiver side */ - InstallPacketSink(rightNodes.Get(0), server_port, socketFactory, - Seconds(0.01), stopTimeSimulation); - // InstallPacketSink(rightNodes.Get(0), server_port, "ns3::UdpSocketFactory", - // Seconds(0.01), stopTimeSimulation); - - /* Install BulkSend application */ - // InstallBulkSend(leftNodes.Get(0), routerToRightIPAddress.GetAddress(1), - // server_port, socketFactory, 2, 0, - // MakeCallback(&CwndChange), bytes_to_send, Seconds(0.2)); - - // Congestion PARAMETERS - uint16_t serverPort = 50000; - Time startDelay = Seconds(1.0); - Time duration = Seconds(5.0); - uint32_t numPackets = 512; - uint32_t packetSize = 1024; - Time interval = MilliSeconds(10); - Ipv4Address receiverAddress = routerToRightIPAddress.GetAddress(1); - - // Schedule the congestion - // Simulator::Schedule(startDelay, [congestionNode, startDelay, duration, - // numPackets, packetSize, interval, - // receiverAddress, serverPort]() { - // Ptr node = congestionNode.Get(0); - // // double startDelaySeconds = startDelay.GetSeconds(); - // // double duration - // SimulateCongestion(node, startDelay, duration, numPackets, packetSize, - // interval, receiverAddress, serverPort); - // }); - - // SimulateCongestion(congestionNode.Get(0), startDelay, duration, numPackets, - // packetSize, interval, receiverAddress, serverPort); - - OnOffHelper onoff( - "ns3::UdpSocketFactory", - InetSocketAddress(routerToRightIPAddress.GetAddress(1), 50000)); - onoff.SetAttribute("PacketSize", UintegerValue(8)); - onoff.SetAttribute("DataRate", DataRateValue(DataRate("200kbps"))); - - ApplicationContainer app = onoff.Install(congestionNode.Get(0)); - app.Start(Seconds(1.0)); - app.Stop(Seconds(3.0)); - - if (storeTraces) { - pointToPointRouter.EnablePcapAll(tracesPath); - } - - // Simulator::Stop(stopTimeSimulation); - Simulator::Run(); - Simulator::Destroy(); - return 0; + // Simulator::Stop(stopTimeSimulation); + Simulator::Run(); + Simulator::Destroy(); + return 0; } From ddeeca532696f67fdad99f7e6f741f764b5a8c0d Mon Sep 17 00:00:00 2001 From: charliebarber Date: Tue, 12 Mar 2024 12:44:17 +0000 Subject: [PATCH 10/28] Full topology combining both UDP and TCP traffic in combined.cc --- src/combined.cc | 224 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 src/combined.cc diff --git a/src/combined.cc b/src/combined.cc new file mode 100644 index 00000000..291d454f --- /dev/null +++ b/src/combined.cc @@ -0,0 +1,224 @@ +#include <__errc> +#include + +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/internet-module.h" +#include "ns3/point-to-point-module.h" +#include "ns3/applications-module.h" +#include "ns3/log.h" + +#include "../libs/frr_queue.h" +#include "../libs/dummy_congestion_policy.h" +#include "../libs/modulo_congestion_policy.h" +#include "../libs/lfa_policy.h" +#include "../libs/random_congestion_policy.h" + +using namespace ns3; + +using CongestionPolicy = RandomCongestionPolicy<50>; +using FRRPolicy = LFAPolicy; + +using SimulationQueue = FRRQueue; + +void toggleCongestion(Ptr queue) +{ + queue->m_congestionPolicy.turnOff(); +} + +NS_OBJECT_ENSURE_REGISTERED(SimulationQueue); + +template +Ptr getDevice(const NetDeviceContainer& devices) +{ + return devices.Get(INDEX)->GetObject(); +} + +template +Ptr getQueue(const NetDeviceContainer& devices) +{ + return DynamicCast(getDevice(devices)->GetQueue()); +} + +template +void setAlternateTarget(const NetDeviceContainer& devices, + Ptr target) +{ + getQueue(devices)->addAlternateTargets(target); +} + +void SetupTCPConfig() +{ + // TCP recovery algorithm + Config::SetDefault( + "ns3::TcpL4Protocol::RecoveryType", + TypeIdValue(TypeId::LookupByName("ns3::TcpClassicRecovery"))); + // Congestion control algorithm + Config::SetDefault("ns3::TcpL4Protocol::SocketType", + StringValue("ns3::TcpLinuxReno")); + Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(1073741824)); + Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(1073741824)); + // Initial congestion window + Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(1)); + // Set delayed ack count + Config::SetDefault("ns3::TcpSocket::DelAckTimeout", TimeValue(Time("1ms"))); + Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(1)); + // Set segment size of packet + Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1024)); + // Enable/disable SACKs (disabled) + Config::SetDefault("ns3::TcpSocketBase::Sack", BooleanValue(false)); + Config::SetDefault("ns3::TcpSocketBase::MinRto", TimeValue(Seconds(1.0))); +} + +// NS_LOG_COMPONENT_DEFINE("CongestionFastReRoute"); +int main(int argc, char* argv[]) +{ + LogComponentEnable("FRRQueue", LOG_LEVEL_LOGIC); + /* + * +----------+ +-----------+ + * |Congestion| | Traffic | + * | Sender | | Sender | + * 0+----+-----+ 1+-----+-----+ + * | | + * | +----------+ | + * +---+ Router +---+ + * | 01 | + * 2+----+-----+--------+ + * | | + * | +-----+----+ + * | | Router | + * | | 03 | + * +----+-----+ 4+----+-----+ + * | Router | | + * | 02 +-------+ + * 3+----+-----+ + * | + * | + * +----+-----+ + * | Receiver | + * | | + * 5+----------+ + */ + // Topology setup + NS_LOG_INFO("Creating Topology"); + NodeContainer nodes; + nodes.Create(6); + Names::Add("CongestionSender", nodes.Get(0)); + Names::Add("TrafficSender", nodes.Get(1)); + Names::Add("Router01", nodes.Get(2)); + Names::Add("Router02", nodes.Get(3)); + Names::Add("Router03", nodes.Get(4)); + Names::Add("Receiver", nodes.Get(5)); + + InternetStackHelper stack; + stack.Install(nodes); + + // Configure PointToPoint link for normal traffic + PointToPointHelper p2p_traffic; + p2p_traffic.SetDeviceAttribute("DataRate", StringValue("1Mbps")); + p2p_traffic.SetChannelAttribute("Delay", StringValue("1ms")); + // Set the custom queue for the device + p2p_traffic.SetQueue(SimulationQueue::getQueueString()); + // Install devices and channels between nodes + NetDeviceContainer devices_0_2 = + p2p_traffic.Install(nodes.Get(0), nodes.Get(2)); + NetDeviceContainer devices_2_3 = + p2p_traffic.Install(nodes.Get(2), nodes.Get(3)); + NetDeviceContainer devices_2_4 = + p2p_traffic.Install(nodes.Get(2), nodes.Get(4)); + NetDeviceContainer devices_4_3 = + p2p_traffic.Install(nodes.Get(4), nodes.Get(3)); + NetDeviceContainer devices_3_5 = + p2p_traffic.Install(nodes.Get(3), nodes.Get(5)); + + // Configure PointToPoint link for congestion link + PointToPointHelper p2p_congestion; + p2p_congestion.SetDeviceAttribute("DataRate", StringValue("1Mbps")); + p2p_congestion.SetChannelAttribute("Delay", StringValue("1ms")); + // Set the custom queue for the device + p2p_congestion.SetQueue(SimulationQueue::getQueueString()); + // Install devices and channels between nodes + NetDeviceContainer devices_1_2 = + p2p_congestion.Install(nodes.Get(1), nodes.Get(2)); + + // Assign IP addresses to subnets + Ipv4AddressHelper address; + address.SetBase("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces_0_2 = address.Assign(devices_0_2); + Ipv4InterfaceContainer interfaces_1_2 = address.Assign(devices_1_2); + address.NewNetwork(); + address.SetBase("10.1.2.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces_2_3 = address.Assign(devices_2_3); + address.NewNetwork(); + address.SetBase("10.1.3.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces_2_4 = address.Assign(devices_2_4); + address.NewNetwork(); + address.SetBase("10.1.4.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces_4_3 = address.Assign(devices_4_3); + address.NewNetwork(); + address.SetBase("10.1.5.0", "255.255.255.0"); + Ipv4InterfaceContainer interfaces_3_5 = address.Assign(devices_3_5); + address.NewNetwork(); + Ipv4GlobalRoutingHelper::PopulateRoutingTables(); + + // Receiver address + Ipv4Addresss receiver_addr = interfaces_3_5.GetAddress(1); + + // UDP Congestion traffic setup + uint16_t udp_port = 5001; + OnOffHelper udp_source("ns3::UdpSocketFactory", + InetSocketAddress(receiver_addr, udp_port)); + udp_source.SetAttribute( + "OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); + udp_source.SetAttribute( + "OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); + udp_source.SetAttribute("DataRate", DataRateValue(DataRate("1Mbps"))); + udp_source.SetAttribute("PacketSize", UintegerValue(1024)); + + ApplicationContainer udp_app = udp_source.Install(nodes.Get(0)); + app.Start(Seconds(2.0)); + app.Stop(Seconds(6.0)); + + // TCP Setup + SetupTCPConfig(); + uint16_t tcp_port = 5002; + BulkSendHelper tcp_source("ns3::TcpSocketFactory", + InetSocketAddress(receiver_addr, tcp_port)); + tcp_source.SetAttribute("MaxBytes", UintegerValue(1000)); // Tweak this + ApplicationContainer tcp_app = tcp_source.Install(nodes.Get(1)); + tcp_app.Start(Seconds(0.0)); + tcp_app.Stop(Seconds(10.0)); + + // Packet sink setup (Receiver node) + PacketSinkHelper sink("ns3::TcpSocketFactory", + InetSocketAddress(Ipv4Address::GetAny(), port)); + ApplicationContainer sink_app = sink.Install(nodes.Get(5)); + tcp_app.Start(Seconds(0.0)); + tcp_app.Start(Seconds(10.0)); + + // NOTE: Is TrafficControlHelper needed here? + + // LFA Alternate Path setup + // Set up an alternate forwarding target, assuming you have an alternate + // path configured + + setAlternateTarget<0>(devices01, getDevice<0>(devices02)); + setAlternateTarget<0>(devices02, getDevice<0>(devices01)); + + setAlternateTarget<0>(devices12, getDevice<1>(devices01)); + setAlternateTarget<1>(devices01, getDevice<0>(devices12)); + + setAlternateTarget<1>(devices02, getDevice<1>(devices12)); + setAlternateTarget<1>(devices12, getDevice<1>(devices02)); + + // toggle off random congestion for all queues except node 0 to node 2 + toggleCongestion(getQueue<0>(devices01)); + toggleCongestion(getQueue<1>(devices01)); + toggleCongestion(getQueue<0>(devices12)); + toggleCongestion(getQueue<1>(devices12)); + toggleCongestion(getQueue<1>(devices02)); + + Simulator::Run(); + Simulator::Destroy(); + return 0; +} From c25fcdd4ff70630f20e8b06932acc71e4afa7f26 Mon Sep 17 00:00:00 2001 From: charliebarber Date: Tue, 12 Mar 2024 12:53:29 +0000 Subject: [PATCH 11/28] Combined setup, need help with alternate routes and also deref zero pointer runtime error --- src/combined.cc | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/combined.cc b/src/combined.cc index 291d454f..2b893190 100644 --- a/src/combined.cc +++ b/src/combined.cc @@ -1,4 +1,3 @@ -#include <__errc> #include #include "ns3/core-module.h" @@ -162,7 +161,7 @@ int main(int argc, char* argv[]) Ipv4GlobalRoutingHelper::PopulateRoutingTables(); // Receiver address - Ipv4Addresss receiver_addr = interfaces_3_5.GetAddress(1); + Ipv4Address receiver_addr = interfaces_3_5.GetAddress(1); // UDP Congestion traffic setup uint16_t udp_port = 5001; @@ -176,8 +175,8 @@ int main(int argc, char* argv[]) udp_source.SetAttribute("PacketSize", UintegerValue(1024)); ApplicationContainer udp_app = udp_source.Install(nodes.Get(0)); - app.Start(Seconds(2.0)); - app.Stop(Seconds(6.0)); + udp_app.Start(Seconds(2.0)); + udp_app.Stop(Seconds(6.0)); // TCP Setup SetupTCPConfig(); @@ -191,7 +190,7 @@ int main(int argc, char* argv[]) // Packet sink setup (Receiver node) PacketSinkHelper sink("ns3::TcpSocketFactory", - InetSocketAddress(Ipv4Address::GetAny(), port)); + InetSocketAddress(Ipv4Address::GetAny(), tcp_port)); ApplicationContainer sink_app = sink.Install(nodes.Get(5)); tcp_app.Start(Seconds(0.0)); tcp_app.Start(Seconds(10.0)); @@ -202,21 +201,15 @@ int main(int argc, char* argv[]) // Set up an alternate forwarding target, assuming you have an alternate // path configured - setAlternateTarget<0>(devices01, getDevice<0>(devices02)); - setAlternateTarget<0>(devices02, getDevice<0>(devices01)); + // TODO: Need some help with setting alternate target + // setAlternateTarget<0>(devices01, getDevice<0>(devices02)); + // setAlternateTarget<0>(devices02, getDevice<0>(devices01)); - setAlternateTarget<0>(devices12, getDevice<1>(devices01)); - setAlternateTarget<1>(devices01, getDevice<0>(devices12)); + // setAlternateTarget<0>(devices12, getDevice<1>(devices01)); + // setAlternateTarget<1>(devices01, getDevice<0>(devices12)); - setAlternateTarget<1>(devices02, getDevice<1>(devices12)); - setAlternateTarget<1>(devices12, getDevice<1>(devices02)); - - // toggle off random congestion for all queues except node 0 to node 2 - toggleCongestion(getQueue<0>(devices01)); - toggleCongestion(getQueue<1>(devices01)); - toggleCongestion(getQueue<0>(devices12)); - toggleCongestion(getQueue<1>(devices12)); - toggleCongestion(getQueue<1>(devices02)); + // setAlternateTarget<1>(devices02, getDevice<1>(devices12)); + // setAlternateTarget<1>(devices12, getDevice<1>(devices02)); Simulator::Run(); Simulator::Destroy(); From a14e4ef13d5610e4cb4dee98892c4451c0e2c904 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Tue, 12 Mar 2024 12:54:44 +0000 Subject: [PATCH 12/28] :loud_sound: added more logging --- libs/basic_congestion.h | 8 +++++++- libs/frr_queue.h | 34 ++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/libs/basic_congestion.h b/libs/basic_congestion.h index 1e2a09d2..bf5cfd8e 100644 --- a/libs/basic_congestion.h +++ b/libs/basic_congestion.h @@ -7,13 +7,19 @@ namespace ns3 template class BasicCongestionPolicy { - static_assert(MAX_USAGE_PERCENTAGE > 0 && MAX_USAGE_PERCENTAGE <= 100, + static_assert(MAX_USAGE_PERCENTAGE >= 0 && MAX_USAGE_PERCENTAGE <= 100, "MAX_USAGE_PERCENTAGE must be between 1 and 100"); public: static bool isCongested(ns3::Queue* queue); }; +template <> +bool BasicCongestionPolicy<0>::isCongested(ns3::Queue* queue) +{ + return true; +} + template <> bool BasicCongestionPolicy<100>::isCongested(ns3::Queue* queue) { diff --git a/libs/frr_queue.h b/libs/frr_queue.h index 3ed72a83..6a594ef5 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -21,6 +21,8 @@ namespace ns3 template class FRRQueue : public Queue { + public: + int m_uid; private: using Queue::GetContainer; using Queue::DoEnqueue; @@ -28,7 +30,6 @@ class FRRQueue : public Queue using Queue::DoRemove; using Queue::DoPeek; - int m_uid; NS_LOG_TEMPLATE_DECLARE; void ForwardToAlternateTarget(Ptr packet); @@ -53,8 +54,12 @@ class FRRQueue : public Queue void addAlternateTargets(DEVICES&&... devices); static const std::string& getQueueString(); + static Mac48Address sinkAddress; }; +template +Mac48Address FRRQueue::sinkAddress; + template int FRRQueue::s_uid = 0; @@ -90,7 +95,7 @@ TypeId FRRQueue::GetTypeId() template bool FRRQueue::Enqueue(Ptr packet) { - NS_LOG_FUNCTION(this << packet); + NS_LOG_LOGIC("(" << m_uid << ") Checking Queue For " << packet << ", uuid:" << packet->GetUid()); if (m_congestionPolicy.isCongested(this)) { NS_LOG_LOGIC("(" << m_uid << ") Congested Route, Rerouting packet: " << packet); @@ -98,22 +103,19 @@ bool FRRQueue::Enqueue(Ptr packet) NS_LOG_LOGIC("(" << m_uid << ") Rerouting complete"); return false; } - NS_LOG_LOGIC("(" << m_uid << ") Enqueued " << packet << " to " - << GetNPackets() << " packets in queue."); + NS_LOG_LOGIC("(" << m_uid << ") Enqueue " << packet << ", uuid:" << packet->GetUid() << + " to curr: " << GetNPackets() << " packets in queue."); DoEnqueue(GetContainer().end(), packet); - NS_LOG_LOGIC("(" << m_uid << ") Enqueued " << packet << " to " - << GetNPackets() << " packets in queue."); return true; } template Ptr FRRQueue::Dequeue() { - NS_LOG_FUNCTION(this); + //NS_LOG_FUNCTION(this); Ptr packet = DoDequeue(GetContainer().begin()); - - NS_LOG_LOGIC("Popped " << packet); + NS_LOG_LOGIC("(" << m_uid << ") Popped " << packet); return packet; } @@ -141,10 +143,18 @@ template void FRRQueue::ForwardToAlternateTarget( Ptr packet) { - Ptr alternativeTarget = m_frrPolicy.selectAlternativeTarget(); + NS_LOG_LOGIC("(" << m_uid << ") Attempting to Forwarding packet to: " << sinkAddress); + Ptr alternativeTarget = m_frrPolicy.selectAlternativeTarget(); if (alternativeTarget) - alternativeTarget->Send(packet, alternativeTarget->GetAddress(), - 0x0800); + { + NS_LOG_LOGIC("(" << m_uid << ") Forwarding packet to: " << sinkAddress); + bool rc = alternativeTarget->Send(packet, sinkAddress, 0x0800); + NS_LOG_LOGIC("(" << m_uid << ") Forwarded packet with: " << rc); + } + else + { + NS_LOG_LOGIC("(" << m_uid << ") No alternative target found, dropping packet."); + } } template From 12b0d68b4ff8d8e4003c40dfdfa3ab1280b93bc8 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Tue, 12 Mar 2024 12:55:03 +0000 Subject: [PATCH 13/28] :test_tube: testing --- src/basic_congestion.cc | 45 ++++++++++++++++++++++++++++++----------- src/lfa_random.cc | 15 ++++++++++++-- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/basic_congestion.cc b/src/basic_congestion.cc index 0c6f23bc..bc3355e1 100644 --- a/src/basic_congestion.cc +++ b/src/basic_congestion.cc @@ -22,7 +22,7 @@ using namespace ns3; using Random = effolkronium::random_static; -using CongestionPolicy = BasicCongestionPolicy<99>; +using CongestionPolicy = BasicCongestionPolicy<50>; using FRRPolicy = LFAPolicy; using SimulationQueue = FRRQueue; @@ -82,7 +82,7 @@ uint8_t delAckCount = 1; uint8_t initialCwnd = 1; // std::string delAckTimeout = "200ms"; std::string delAckTimeout = "1ms"; -std::string socketFactory = "ns3::TcpSocketFactory"; +std::string socketFactory = "ns3::UdpSocketFactory"; std::string qdiscTypeId = "ns3::PFifoFastQueueDisc"; std::string tcpRecovery = "ns3::TcpClassicRecovery"; // std::string tcpVariantId = "ns3::TcpCubic"; @@ -91,8 +91,8 @@ bool enableSack = false; double minRTO = 1.0; // ---[TOPOLOGY PARAMETERS]--- -std::string bandwidth_bottleneck = "1Mbps"; -std::string bandwidth_access = "20Mbps"; +std::string bandwidth_bottleneck = "5kbps"; +std::string bandwidth_access = "5Mbps"; std::string delay_access = "15ms"; std::string delay_bottleneck = "20ms"; std::string delay_serialization = "1.9ms"; @@ -345,30 +345,50 @@ int main(int argc, char* argv[]) */ NetDeviceContainer r1r2ND = pointToPointRouter.Install(routers.Get(0), routers.Get(1)); + std::cout << "0 -> 1: " << getQueue<0>(r1r2ND)->m_uid << std::endl; + std::cout << "1 -> 0: " << getQueue<1>(r1r2ND)->m_uid << std::endl; NetDeviceContainer r1r3ND = pointToPointRouter.Install(routers.Get(0), routers.Get(2)); - NetDeviceContainer r3r2ND = - pointToPointRouter.Install(routers.Get(2), routers.Get(1)); + std::cout << "0 -> 2: " << getQueue<0>(r1r3ND)->m_uid << std::endl; + std::cout << "2 -> 0: " << getQueue<1>(r1r3ND)->m_uid << std::endl; + + PointToPointHelper pointToPointRerouter; + pointToPointRerouter.SetQueue(SimulationQueue::getQueueString()); + pointToPointRerouter.SetDeviceAttribute("DataRate", + StringValue(bandwidth_access)); + pointToPointRerouter.SetChannelAttribute("Delay", + StringValue(delay_access)); + NetDeviceContainer r3r2ND = + pointToPointRerouter.Install(routers.Get(2), routers.Get(1)); + std::cout << "2 -> 1: " << getQueue<0>(r3r2ND)->m_uid << std::endl; + std::cout << "1 -> 2: " << getQueue<1>(r3r2ND)->m_uid << std::endl; + setAlternateTarget<0>(r1r2ND, getDevice<0>(r1r3ND)); // setAlternateTarget<0>(r1r2ND, getDevice<0>(devices02)); // Create the point-to-point link helpers and connect leaf nodes to router PointToPointHelper pointToPointLeaf; - // pointToPointLeaf.SetQueue(SimulationQueue::getQueueString()); + pointToPointLeaf.SetQueue(SimulationQueue::getQueueString()); pointToPointLeaf.SetDeviceAttribute("DataRate", StringValue(bandwidth_access)); pointToPointLeaf.SetChannelAttribute("Delay", StringValue(delay_access)); NetDeviceContainer leftToRouter = pointToPointLeaf.Install(leftNodes.Get(0), routers.Get(0)); + std::cout << "L -> 0: " << getQueue<0>(leftToRouter)->m_uid << std::endl; + std::cout << "0 -> L: " << getQueue<1>(leftToRouter)->m_uid << std::endl; NetDeviceContainer routerToRight = pointToPointLeaf.Install(routers.Get(1), rightNodes.Get(0)); + std::cout << "1 -> R: " << getQueue<0>(routerToRight)->m_uid << std::endl; + std::cout << "R -> 1: " << getQueue<1>(routerToRight)->m_uid << std::endl; // Link CongestioNSender to Router1 NetDeviceContainer congestionSenderToRouter = pointToPointLeaf.Install(congestionNode.Get(0), routers.Get(0)); + std::cout << "C -> 0: " << getQueue<0>(congestionSenderToRouter)->m_uid << std::endl; + std::cout << "0 -> C: " << getQueue<1>(congestionSenderToRouter)->m_uid << std::endl; InternetStackHelper internetStack; internetStack.Install(leftNodes); @@ -377,14 +397,14 @@ int main(int argc, char* argv[]) internetStack.Install(congestionNode); Ipv4AddressHelper ipAddresses("10.0.0.0", "255.255.255.0"); + Ipv4InterfaceContainer routerToRightIPAddress = + ipAddresses.Assign(routerToRight); + ipAddresses.NewNetwork(); Ipv4InterfaceContainer r1r2IPAddress = ipAddresses.Assign(r1r2ND); ipAddresses.NewNetwork(); Ipv4InterfaceContainer leftToRouterIPAddress = ipAddresses.Assign(leftToRouter); ipAddresses.NewNetwork(); - Ipv4InterfaceContainer routerToRightIPAddress = - ipAddresses.Assign(routerToRight); - ipAddresses.NewNetwork(); Ipv4InterfaceContainer congestionToRouter0IPAddress = ipAddresses.Assign(congestionSenderToRouter); ipAddresses.NewNetwork(); @@ -396,6 +416,7 @@ int main(int argc, char* argv[]) Ipv4GlobalRoutingHelper::PopulateRoutingTables(); + SimulationQueue::sinkAddress = Mac48Address::ConvertFrom(getDevice<1>(routerToRight)->GetAddress()); // Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", // QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, // projected_queue_max_packets))); @@ -483,9 +504,9 @@ int main(int argc, char* argv[]) OnOffHelper onoff( "ns3::UdpSocketFactory", - InetSocketAddress(routerToRightIPAddress.GetAddress(1), 50000)); + InetSocketAddress(routerToRightIPAddress.GetAddress(1), serverPort)); onoff.SetAttribute("PacketSize", UintegerValue(8)); - onoff.SetAttribute("DataRate", DataRateValue(DataRate("200kbps"))); + onoff.SetAttribute("DataRate", DataRateValue(DataRate("5kbps"))); ApplicationContainer app = onoff.Install(congestionNode.Get(0)); app.Start(Seconds(1.0)); diff --git a/src/lfa_random.cc b/src/lfa_random.cc index a7287394..602c9c9b 100644 --- a/src/lfa_random.cc +++ b/src/lfa_random.cc @@ -12,10 +12,12 @@ #include "../libs/modulo_congestion_policy.h" #include "../libs/lfa_policy.h" #include "../libs/random_congestion_policy.h" +#include "../libs/basic_congestion.h" using namespace ns3; using CongestionPolicy = RandomCongestionPolicy<50>; +//using CongestionPolicy = BasicCongestionPolicy<50>; using FRRPolicy = LFAPolicy; using SimulationQueue = FRRQueue; @@ -68,11 +70,19 @@ int main(int argc, char* argv[]) // Install devices and channels between nodes NetDeviceContainer devices01 = p2p.Install(nodes.Get(0), nodes.Get(1)); + std::cout << "0 -> 1: " << getQueue<0>(devices01)->m_uid << std::endl; + std::cout << "1 -> 0: " << getQueue<1>(devices01)->m_uid << std::endl; NetDeviceContainer devices12 = p2p.Install(nodes.Get(1), nodes.Get(2)); + std::cout << "1 -> 2: " << getQueue<0>(devices12)->m_uid << std::endl; + std::cout << "2 -> 1: " << getQueue<1>(devices12)->m_uid << std::endl; // Add the missing link between Node 0 and Node 2 to fully connect the // network NetDeviceContainer devices02 = p2p.Install(nodes.Get(0), nodes.Get(2)); + std::cout << "0 -> 2: " << getQueue<0>(devices02)->m_uid << std::endl; + std::cout << "2 -> 0: " << getQueue<1>(devices02)->m_uid << std::endl; + + SimulationQueue::sinkAddress = Mac48Address::ConvertFrom(getDevice<1>(devices12)->GetAddress()); // Assign IP addresses Ipv4AddressHelper address; address.SetBase("10.1.1.0", "255.255.255.0"); @@ -83,7 +93,8 @@ int main(int argc, char* argv[]) Ipv4InterfaceContainer interfaces02 = address.Assign(devices02); Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - + Ptr routingStream = Create(&std::cout); + Ipv4GlobalRoutingHelper::PrintRoutingTableAllAt(Seconds(1), routingStream); /* Configure the application to generate traffic * we have node 0 sending traffic to node 2 * @@ -100,7 +111,7 @@ int main(int argc, char* argv[]) StringValue("ns3::ConstantRandomVariable[Constant=1]")); onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); - onoff.SetAttribute("DataRate", DataRateValue(DataRate("1Mbps"))); + onoff.SetAttribute("DataRate", DataRateValue(DataRate("100kbps"))); onoff.SetAttribute("PacketSize", UintegerValue(1024)); ApplicationContainer app = onoff.Install(nodes.Get(0)); From 15afa1b43614877dd1d85c0ef52d163b6d364ead Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Tue, 12 Mar 2024 12:56:23 +0000 Subject: [PATCH 14/28] :art: format files --- libs/basic_congestion.h | 2 +- libs/frr_queue.h | 35 +++++++++++++++++++---------------- src/basic_congestion.cc | 15 +++++++++------ src/lfa_random.cc | 9 +++++---- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/libs/basic_congestion.h b/libs/basic_congestion.h index bf5cfd8e..ed99a359 100644 --- a/libs/basic_congestion.h +++ b/libs/basic_congestion.h @@ -17,7 +17,7 @@ class BasicCongestionPolicy template <> bool BasicCongestionPolicy<0>::isCongested(ns3::Queue* queue) { - return true; + return true; } template <> diff --git a/libs/frr_queue.h b/libs/frr_queue.h index 6a594ef5..e56d1216 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -21,8 +21,9 @@ namespace ns3 template class FRRQueue : public Queue { - public: + public: int m_uid; + private: using Queue::GetContainer; using Queue::DoEnqueue; @@ -95,7 +96,8 @@ TypeId FRRQueue::GetTypeId() template bool FRRQueue::Enqueue(Ptr packet) { - NS_LOG_LOGIC("(" << m_uid << ") Checking Queue For " << packet << ", uuid:" << packet->GetUid()); + NS_LOG_LOGIC("(" << m_uid << ") Checking Queue For " << packet + << ", uuid:" << packet->GetUid()); if (m_congestionPolicy.isCongested(this)) { NS_LOG_LOGIC("(" << m_uid << ") Congested Route, Rerouting packet: " << packet); @@ -103,8 +105,9 @@ bool FRRQueue::Enqueue(Ptr packet) NS_LOG_LOGIC("(" << m_uid << ") Rerouting complete"); return false; } - NS_LOG_LOGIC("(" << m_uid << ") Enqueue " << packet << ", uuid:" << packet->GetUid() << - " to curr: " << GetNPackets() << " packets in queue."); + NS_LOG_LOGIC("(" << m_uid << ") Enqueue " << packet + << ", uuid:" << packet->GetUid() + << " to curr: " << GetNPackets() << " packets in queue."); DoEnqueue(GetContainer().end(), packet); return true; } @@ -112,7 +115,7 @@ bool FRRQueue::Enqueue(Ptr packet) template Ptr FRRQueue::Dequeue() { - //NS_LOG_FUNCTION(this); + // NS_LOG_FUNCTION(this); Ptr packet = DoDequeue(GetContainer().begin()); NS_LOG_LOGIC("(" << m_uid << ") Popped " << packet); @@ -143,17 +146,17 @@ template void FRRQueue::ForwardToAlternateTarget( Ptr packet) { - NS_LOG_LOGIC("(" << m_uid << ") Attempting to Forwarding packet to: " << sinkAddress); - Ptr alternativeTarget = m_frrPolicy.selectAlternativeTarget(); - if (alternativeTarget) - { - NS_LOG_LOGIC("(" << m_uid << ") Forwarding packet to: " << sinkAddress); - bool rc = alternativeTarget->Send(packet, sinkAddress, 0x0800); - NS_LOG_LOGIC("(" << m_uid << ") Forwarded packet with: " << rc); - } - else - { - NS_LOG_LOGIC("(" << m_uid << ") No alternative target found, dropping packet."); + NS_LOG_LOGIC("(" << m_uid << ") Attempting to Forwarding packet to: " + << sinkAddress); + Ptr alternativeTarget = + m_frrPolicy.selectAlternativeTarget(); + if (alternativeTarget) { + NS_LOG_LOGIC("(" << m_uid << ") Forwarding packet to: " << sinkAddress); + bool rc = alternativeTarget->Send(packet, sinkAddress, 0x0800); + NS_LOG_LOGIC("(" << m_uid << ") Forwarded packet with: " << rc); + } else { + NS_LOG_LOGIC("(" << m_uid + << ") No alternative target found, dropping packet."); } } diff --git a/src/basic_congestion.cc b/src/basic_congestion.cc index bc3355e1..f60383e0 100644 --- a/src/basic_congestion.cc +++ b/src/basic_congestion.cc @@ -356,15 +356,15 @@ int main(int argc, char* argv[]) PointToPointHelper pointToPointRerouter; pointToPointRerouter.SetQueue(SimulationQueue::getQueueString()); pointToPointRerouter.SetDeviceAttribute("DataRate", - StringValue(bandwidth_access)); + StringValue(bandwidth_access)); pointToPointRerouter.SetChannelAttribute("Delay", - StringValue(delay_access)); + StringValue(delay_access)); NetDeviceContainer r3r2ND = pointToPointRerouter.Install(routers.Get(2), routers.Get(1)); std::cout << "2 -> 1: " << getQueue<0>(r3r2ND)->m_uid << std::endl; std::cout << "1 -> 2: " << getQueue<1>(r3r2ND)->m_uid << std::endl; - + setAlternateTarget<0>(r1r2ND, getDevice<0>(r1r3ND)); // setAlternateTarget<0>(r1r2ND, getDevice<0>(devices02)); @@ -387,8 +387,10 @@ int main(int argc, char* argv[]) // Link CongestioNSender to Router1 NetDeviceContainer congestionSenderToRouter = pointToPointLeaf.Install(congestionNode.Get(0), routers.Get(0)); - std::cout << "C -> 0: " << getQueue<0>(congestionSenderToRouter)->m_uid << std::endl; - std::cout << "0 -> C: " << getQueue<1>(congestionSenderToRouter)->m_uid << std::endl; + std::cout << "C -> 0: " << getQueue<0>(congestionSenderToRouter)->m_uid + << std::endl; + std::cout << "0 -> C: " << getQueue<1>(congestionSenderToRouter)->m_uid + << std::endl; InternetStackHelper internetStack; internetStack.Install(leftNodes); @@ -416,7 +418,8 @@ int main(int argc, char* argv[]) Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - SimulationQueue::sinkAddress = Mac48Address::ConvertFrom(getDevice<1>(routerToRight)->GetAddress()); + SimulationQueue::sinkAddress = + Mac48Address::ConvertFrom(getDevice<1>(routerToRight)->GetAddress()); // Config::SetDefault("ns3::PfifoFastQueueDisc::MaxSize", // QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, // projected_queue_max_packets))); diff --git a/src/lfa_random.cc b/src/lfa_random.cc index 602c9c9b..edd72497 100644 --- a/src/lfa_random.cc +++ b/src/lfa_random.cc @@ -17,7 +17,7 @@ using namespace ns3; using CongestionPolicy = RandomCongestionPolicy<50>; -//using CongestionPolicy = BasicCongestionPolicy<50>; +// using CongestionPolicy = BasicCongestionPolicy<50>; using FRRPolicy = LFAPolicy; using SimulationQueue = FRRQueue; @@ -81,8 +81,8 @@ int main(int argc, char* argv[]) std::cout << "0 -> 2: " << getQueue<0>(devices02)->m_uid << std::endl; std::cout << "2 -> 0: " << getQueue<1>(devices02)->m_uid << std::endl; - - SimulationQueue::sinkAddress = Mac48Address::ConvertFrom(getDevice<1>(devices12)->GetAddress()); + SimulationQueue::sinkAddress = + Mac48Address::ConvertFrom(getDevice<1>(devices12)->GetAddress()); // Assign IP addresses Ipv4AddressHelper address; address.SetBase("10.1.1.0", "255.255.255.0"); @@ -93,7 +93,8 @@ int main(int argc, char* argv[]) Ipv4InterfaceContainer interfaces02 = address.Assign(devices02); Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - Ptr routingStream = Create(&std::cout); + Ptr routingStream = + Create(&std::cout); Ipv4GlobalRoutingHelper::PrintRoutingTableAllAt(Seconds(1), routingStream); /* Configure the application to generate traffic * we have node 0 sending traffic to node 2 From 9beeb623df0847738afefb19c82259f6454c4c93 Mon Sep 17 00:00:00 2001 From: charliebarber Date: Tue, 12 Mar 2024 16:43:54 +0000 Subject: [PATCH 15/28] Pcaps enabled --- traces/placeholder | 1 - 1 file changed, 1 deletion(-) delete mode 100644 traces/placeholder diff --git a/traces/placeholder b/traces/placeholder deleted file mode 100644 index 8b137891..00000000 --- a/traces/placeholder +++ /dev/null @@ -1 +0,0 @@ - From bed7a0df4b408a9b04bc17e3ed452bc12b1f15ef Mon Sep 17 00:00:00 2001 From: charliebarber Date: Tue, 12 Mar 2024 16:44:12 +0000 Subject: [PATCH 16/28] Pcaps enabled. --- src/combined.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/combined.cc b/src/combined.cc index 2b893190..0106cd95 100644 --- a/src/combined.cc +++ b/src/combined.cc @@ -175,7 +175,7 @@ int main(int argc, char* argv[]) udp_source.SetAttribute("PacketSize", UintegerValue(1024)); ApplicationContainer udp_app = udp_source.Install(nodes.Get(0)); - udp_app.Start(Seconds(2.0)); + udp_app.Start(Seconds(3.0)); udp_app.Stop(Seconds(6.0)); // TCP Setup @@ -183,7 +183,7 @@ int main(int argc, char* argv[]) uint16_t tcp_port = 5002; BulkSendHelper tcp_source("ns3::TcpSocketFactory", InetSocketAddress(receiver_addr, tcp_port)); - tcp_source.SetAttribute("MaxBytes", UintegerValue(1000)); // Tweak this + tcp_source.SetAttribute("MaxBytes", UintegerValue(10000)); // Tweak this ApplicationContainer tcp_app = tcp_source.Install(nodes.Get(1)); tcp_app.Start(Seconds(0.0)); tcp_app.Stop(Seconds(10.0)); @@ -202,6 +202,7 @@ int main(int argc, char* argv[]) // path configured // TODO: Need some help with setting alternate target + setAlternateTarget<0>(devices_0_2, getDevice<1>(devices_2_4)); // setAlternateTarget<0>(devices01, getDevice<0>(devices02)); // setAlternateTarget<0>(devices02, getDevice<0>(devices01)); @@ -211,6 +212,9 @@ int main(int argc, char* argv[]) // setAlternateTarget<1>(devices02, getDevice<1>(devices12)); // setAlternateTarget<1>(devices12, getDevice<1>(devices02)); + p2p_traffic.EnablePcapAll("traces/"); + p2p_congestion.EnablePcapAll("traces/"); + Simulator::Run(); Simulator::Destroy(); return 0; From 0385b42c46ce6ed15b6ba529cf61c16087e2b797 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:55:59 +0000 Subject: [PATCH 17/28] :construction: wip --- libs/random_congestion_policy.h | 13 ++++++++++--- src/combined.cc | 8 +++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/libs/random_congestion_policy.h b/libs/random_congestion_policy.h index c0041286..4a1c17e4 100644 --- a/libs/random_congestion_policy.h +++ b/libs/random_congestion_policy.h @@ -9,14 +9,16 @@ class RandomCongestionPolicy static_assert(PERCENTAGE >= 0 && PERCENTAGE <= 100, "Percentage must be between 0 and 100"); - bool m_off; + bool m_off = true; + bool m_enabled = false; public: RandomCongestionPolicy() = default; bool isCongested(ns3::Queue* queue) const { - std::random_device rd; + if (!m_enabled) return false; + std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(0, 100); return !m_off && dis(gen) < PERCENTAGE; @@ -24,7 +26,12 @@ class RandomCongestionPolicy void turnOff() { - m_off = true; + m_off = false; + } + + void enable() + { + m_enabled = true; } }; diff --git a/src/combined.cc b/src/combined.cc index 0106cd95..58e23a54 100644 --- a/src/combined.cc +++ b/src/combined.cc @@ -20,9 +20,9 @@ using FRRPolicy = LFAPolicy; using SimulationQueue = FRRQueue; -void toggleCongestion(Ptr queue) +void enableRerouting(Ptr queue) { - queue->m_congestionPolicy.turnOff(); + queue->m_congestionPolicy.enable(); } NS_OBJECT_ENSURE_REGISTERED(SimulationQueue); @@ -202,7 +202,7 @@ int main(int argc, char* argv[]) // path configured // TODO: Need some help with setting alternate target - setAlternateTarget<0>(devices_0_2, getDevice<1>(devices_2_4)); + setAlternateTarget<0>(devices_2_3, getDevice<0>(devices_2_4)); // setAlternateTarget<0>(devices01, getDevice<0>(devices02)); // setAlternateTarget<0>(devices02, getDevice<0>(devices01)); @@ -212,6 +212,8 @@ int main(int argc, char* argv[]) // setAlternateTarget<1>(devices02, getDevice<1>(devices12)); // setAlternateTarget<1>(devices12, getDevice<1>(devices02)); + enableRerouting(getQueue<0>(devices_2_3)); + p2p_traffic.EnablePcapAll("traces/"); p2p_congestion.EnablePcapAll("traces/"); From 46cbe1143bd1022e3bfa4758576a73a306cb369c Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Tue, 12 Mar 2024 17:41:51 +0000 Subject: [PATCH 18/28] :construction: wip --- src/combined.cc | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/combined.cc b/src/combined.cc index 58e23a54..54382c86 100644 --- a/src/combined.cc +++ b/src/combined.cc @@ -12,17 +12,18 @@ #include "../libs/modulo_congestion_policy.h" #include "../libs/lfa_policy.h" #include "../libs/random_congestion_policy.h" +#include "../libs/basic_congestion.h" using namespace ns3; -using CongestionPolicy = RandomCongestionPolicy<50>; +using CongestionPolicy = BasicCongestionPolicy<0>; using FRRPolicy = LFAPolicy; using SimulationQueue = FRRQueue; void enableRerouting(Ptr queue) { - queue->m_congestionPolicy.enable(); + //queue->m_congestionPolicy.enable(); } NS_OBJECT_ENSURE_REGISTERED(SimulationQueue); @@ -117,12 +118,19 @@ int main(int argc, char* argv[]) p2p_traffic.SetDeviceAttribute("DataRate", StringValue("1Mbps")); p2p_traffic.SetChannelAttribute("Delay", StringValue("1ms")); // Set the custom queue for the device - p2p_traffic.SetQueue(SimulationQueue::getQueueString()); + p2p_traffic.SetQueue("ns3::DropTailQueue"); // Install devices and channels between nodes + + PointToPointHelper p2p_congested_link; + p2p_congested_link.SetDeviceAttribute("DataRate", StringValue("1Mbps")); + p2p_congested_link.SetChannelAttribute("Delay", StringValue("1ms")); + + p2p_congested_link.SetQueue(SimulationQueue::getQueueString()); + NetDeviceContainer devices_0_2 = p2p_traffic.Install(nodes.Get(0), nodes.Get(2)); NetDeviceContainer devices_2_3 = - p2p_traffic.Install(nodes.Get(2), nodes.Get(3)); + p2p_congested_link.Install(nodes.Get(2), nodes.Get(3)); NetDeviceContainer devices_2_4 = p2p_traffic.Install(nodes.Get(2), nodes.Get(4)); NetDeviceContainer devices_4_3 = @@ -135,7 +143,7 @@ int main(int argc, char* argv[]) p2p_congestion.SetDeviceAttribute("DataRate", StringValue("1Mbps")); p2p_congestion.SetChannelAttribute("Delay", StringValue("1ms")); // Set the custom queue for the device - p2p_congestion.SetQueue(SimulationQueue::getQueueString()); + p2p_congestion.SetQueue("ns3::DropTailQueue"); // Install devices and channels between nodes NetDeviceContainer devices_1_2 = p2p_congestion.Install(nodes.Get(1), nodes.Get(2)); @@ -195,6 +203,7 @@ int main(int argc, char* argv[]) tcp_app.Start(Seconds(0.0)); tcp_app.Start(Seconds(10.0)); + SimulationQueue::sinkAddress = Mac48Address::ConvertFrom(getDevice<1>(devices_3_5)->GetAddress()); // NOTE: Is TrafficControlHelper needed here? // LFA Alternate Path setup @@ -203,6 +212,7 @@ int main(int argc, char* argv[]) // TODO: Need some help with setting alternate target setAlternateTarget<0>(devices_2_3, getDevice<0>(devices_2_4)); + setAlternateTarget<1>(devices_2_3, getDevice<1>(devices_4_3)); // setAlternateTarget<0>(devices01, getDevice<0>(devices02)); // setAlternateTarget<0>(devices02, getDevice<0>(devices01)); @@ -212,7 +222,7 @@ int main(int argc, char* argv[]) // setAlternateTarget<1>(devices02, getDevice<1>(devices12)); // setAlternateTarget<1>(devices12, getDevice<1>(devices02)); - enableRerouting(getQueue<0>(devices_2_3)); + //enableRerouting(getQueue<0>(devices_2_3)); p2p_traffic.EnablePcapAll("traces/"); p2p_congestion.EnablePcapAll("traces/"); From 05ed7e0e6b30490e53961aec1e9a3c3e13a8e2f2 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Tue, 12 Mar 2024 17:53:24 +0000 Subject: [PATCH 19/28] :sparkles: change the protocol number to 4 --- libs/frr_queue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/frr_queue.h b/libs/frr_queue.h index e56d1216..96f59984 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -152,7 +152,7 @@ void FRRQueue::ForwardToAlternateTarget( m_frrPolicy.selectAlternativeTarget(); if (alternativeTarget) { NS_LOG_LOGIC("(" << m_uid << ") Forwarding packet to: " << sinkAddress); - bool rc = alternativeTarget->Send(packet, sinkAddress, 0x0800); + bool rc = alternativeTarget->Send(packet, sinkAddress, 0x04); NS_LOG_LOGIC("(" << m_uid << ") Forwarded packet with: " << rc); } else { NS_LOG_LOGIC("(" << m_uid From ba93070912c5a749031d9b5e3a7f127f79648a8a Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Tue, 12 Mar 2024 23:53:59 +0000 Subject: [PATCH 20/28] :bug: fix the frr queue --- libs/frr_queue.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/frr_queue.h b/libs/frr_queue.h index 96f59984..53985555 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -152,7 +152,9 @@ void FRRQueue::ForwardToAlternateTarget( m_frrPolicy.selectAlternativeTarget(); if (alternativeTarget) { NS_LOG_LOGIC("(" << m_uid << ") Forwarding packet to: " << sinkAddress); - bool rc = alternativeTarget->Send(packet, sinkAddress, 0x04); + PppHeader pppHeader; + packet->RemoveHeader(pppHeader); + bool rc = alternativeTarget->Send(packet, sinkAddress, 0x800); NS_LOG_LOGIC("(" << m_uid << ") Forwarded packet with: " << rc); } else { NS_LOG_LOGIC("(" << m_uid From 4118192e5ade69b3097f89c402ab47727a625826 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Thu, 14 Mar 2024 02:42:14 +0000 Subject: [PATCH 21/28] :sparkles: add queue base to upcast templated queue --- libs/frr_queue_base.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 libs/frr_queue_base.h diff --git a/libs/frr_queue_base.h b/libs/frr_queue_base.h new file mode 100644 index 00000000..04a5e024 --- /dev/null +++ b/libs/frr_queue_base.h @@ -0,0 +1,28 @@ +#ifndef FRR_QUEUE_BASE_H +#define FRR_QUEUE_BASE_H + +#include "ns3/queue.h" +#include "ns3/packet.h" + +namespace ns3 +{ + +class FRRQueueBase : public Queue +{ + protected: + using Queue::GetContainer; + using Queue::DoEnqueue; + using Queue::DoDequeue; + using Queue::DoRemove; + using Queue::DoPeek; + + public: + FRRQueueBase() = default; + virtual ~FRRQueueBase() = default; + + virtual bool isCongested() = 0; +}; + +} // namespace ns3 + +#endif From f17d3204de98fcc7b2056d71dc37ab75d0871b23 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Thu, 14 Mar 2024 02:42:48 +0000 Subject: [PATCH 22/28] :sparkles: reconfigure the frr queue to handle only congestion --- libs/frr_queue.h | 136 +++++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 63 deletions(-) diff --git a/libs/frr_queue.h b/libs/frr_queue.h index ac7c6765..7386790e 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -7,26 +7,28 @@ #include #include // For __cxa_demangle +#include "point_to_point_frr_net_device.h" #include "ns3/object-base.h" -#include "ns3/queue.h" -#include "ns3/packet.h" -#include "ns3/point-to-point-net-device.h" #include +#include "frr_queue_base.h" #define STRINGIFY_TYPE_ALIAS(alias) typeid(alias).name() namespace ns3 { -template -class FRRQueue : public Queue +template +class FRRQueue : public FRRQueueBase { + public: + int m_uid; + private: - using Queue::GetContainer; - using Queue::DoEnqueue; - using Queue::DoDequeue; - using Queue::DoRemove; - using Queue::DoPeek; + using FRRQueueBase::DoDequeue; + using FRRQueueBase::DoEnqueue; + using FRRQueueBase::DoPeek; + using FRRQueueBase::DoRemove; + using FRRQueueBase::GetContainer; NS_LOG_TEMPLATE_DECLARE; @@ -40,40 +42,41 @@ class FRRQueue : public Queue virtual Ptr Peek() const override; public: - FRR_POLICY m_frrPolicy; + static int s_uid; CONGESTION_POLICY m_congestionPolicy; static TypeId GetTypeId(); FRRQueue(); - ~FRRQueue(); - - template - void addAlternateTargets(DEVICES&&... devices); + virtual ~FRRQueue() = default; + virtual bool isCongested() override; static const std::string& getQueueString(); }; -template -FRRQueue::FRRQueue() - : Queue(), NS_LOG_TEMPLATE_DEFINE("FRRQueue") +template +bool FRRQueue::isCongested() { - NS_LOG_FUNCTION(this); + return m_congestionPolicy.isCongested(this); } -template -FRRQueue::~FRRQueue() +template +int FRRQueue::s_uid = 0; + +template +FRRQueue::FRRQueue() + : FRRQueueBase(), m_uid(s_uid++), NS_LOG_TEMPLATE_DEFINE("FRRQueue") { NS_LOG_FUNCTION(this); } -template -TypeId FRRQueue::GetTypeId() +template +TypeId FRRQueue::GetTypeId() { static TypeId tid = TypeId(getQueueString()) .SetParent>() .SetGroupName("Network") - .template AddConstructor>() + .template AddConstructor>() .AddAttribute("MaxSize", "The max queue size", QueueSizeValue(QueueSize("100p")), MakeQueueSizeAccessor(&QueueBase::SetMaxSize, @@ -82,35 +85,37 @@ TypeId FRRQueue::GetTypeId() return tid; } -template -bool FRRQueue::Enqueue(Ptr packet) +template +bool FRRQueue::Enqueue(Ptr packet) { - NS_LOG_FUNCTION(this << packet); - if (m_congestionPolicy.isCongested(GetContainer())) { - NS_LOG_LOGIC("Congested Route, Rerouting packet: " << packet); - ForwardToAlternateTarget(packet); - NS_LOG_LOGIC("Rerouting complete"); + return DoEnqueue(GetContainer().end(), packet); + + NS_LOG_LOGIC("(" << m_uid << ") Checking Queue For " << packet + << ", uuid:" << packet->GetUid()); + if (m_congestionPolicy.isCongested(this)) { + NS_LOG_LOGIC("(" << m_uid + << ") Congested Route, Rerouting packet: " << packet); + // ForwardToAlternateTarget(packet); + NS_LOG_LOGIC("(" << m_uid << ") Rerouting complete"); return false; } - NS_LOG_LOGIC("Enqueued " << packet << " to " << GetContainer().size() - << " packets in queue."); - DoEnqueue(GetContainer().end(), packet); - return true; + NS_LOG_LOGIC("(" << m_uid << ") Enqueue " << packet + << ", uuid:" << packet->GetUid() + << " to curr: " << GetNPackets() << " packets in queue."); } -template -Ptr FRRQueue::Dequeue() +template +Ptr FRRQueue::Dequeue() { - NS_LOG_FUNCTION(this); + // NS_LOG_FUNCTION(this); Ptr packet = DoDequeue(GetContainer().begin()); - - NS_LOG_LOGIC("Popped " << packet); + NS_LOG_LOGIC("(" << m_uid << ") Popped " << packet); return packet; } -template -Ptr FRRQueue::Remove() +template +Ptr FRRQueue::Remove() { NS_LOG_FUNCTION(this); @@ -121,34 +126,39 @@ Ptr FRRQueue::Remove() return packet; } -template -Ptr FRRQueue::Peek() const +template +Ptr FRRQueue::Peek() const { NS_LOG_FUNCTION(this); return DoPeek(GetContainer().begin()); } -template -void FRRQueue::ForwardToAlternateTarget( +/* +template +void FRRQueue::ForwardToAlternateTarget( Ptr packet) { - auto alternativeTarget = m_frrPolicy.selectAlternativeTarget(); - alternativeTarget->Send(packet, alternativeTarget->GetAddress(), 0x0800); -} - -template -template -void FRRQueue::addAlternateTargets( - DEVICES&&... devices) -{ - m_frrPolicy.addAlternateTargets(std::forward(devices)...); + Ptr alternativeTarget = + m_frrPolicy.selectAlternativeTarget(); + if (alternativeTarget) { + PppHeader header; + packet->RemoveHeader(header, 2); + Ipv4Header ipHeader; + packet->PeekHeader(ipHeader); + NS_LOG_LOGIC("(" << m_uid << ") Forwarding packet to: " << +ipHeader.GetDestination()); bool rc = alternativeTarget->Send(packet, +ipHeader.GetDestination(), 0x0800); NS_LOG_LOGIC("(" << m_uid << ") Forwarded +packet with: " << rc); } else { NS_LOG_LOGIC("(" << m_uid + << ") No alternative target found, dropping packet."); + } } +*/ -template -std::string FRRQueue::makeQueueString() +template +std::string FRRQueue::makeQueueString() { - using QueueType = FRRQueue; + using QueueType = FRRQueue; int status; char* demangled = abi::__cxa_demangle(STRINGIFY_TYPE_ALIAS(QueueType), nullptr, nullptr, &status); @@ -159,15 +169,15 @@ std::string FRRQueue::makeQueueString() return result; } -template -const std::string& FRRQueue::getQueueString() +template +const std::string& FRRQueue::getQueueString() { const static std::string result = - FRRQueue::makeQueueString(); + FRRQueue::makeQueueString(); return result; } -NS_LOG_COMPONENT_DEFINE("FRRQueue"); +// NS_LOG_COMPONENT_DEFINE("FRRQueue"); } // namespace ns3 From 29792f7028f3a23483660fa3af271eb0938def4b Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Thu, 14 Mar 2024 02:43:08 +0000 Subject: [PATCH 23/28] :sparkles: add custom point to point net device for frr --- libs/point_to_point_frr_net_device.h | 1161 ++++++++++++++++++++++++++ 1 file changed, 1161 insertions(+) create mode 100644 libs/point_to_point_frr_net_device.h diff --git a/libs/point_to_point_frr_net_device.h b/libs/point_to_point_frr_net_device.h new file mode 100644 index 00000000..df431089 --- /dev/null +++ b/libs/point_to_point_frr_net_device.h @@ -0,0 +1,1161 @@ +/* + * Copyright (c) 2007, 2008 University of Washington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef POINT_TO_POINT_FRR_NET_DEVICE_H +#define POINT_TO_POINT_FRR_NET_DEVICE_H + +#include "ns3/address.h" +#include "ns3/callback.h" +#include "ns3/data-rate.h" +#include "ns3/mac48-address.h" +#include "ns3/net-device.h" +#include "ns3/node.h" +#include "ns3/nstime.h" +#include "ns3/packet.h" +#include "ns3/ptr.h" +#include "ns3/queue-fwd.h" +#include "ns3/traced-callback.h" + +#include "ns3/ppp-header.h" + +#include "ns3/error-model.h" +#include "ns3/llc-snap-header.h" +#include "ns3/log.h" +#include "ns3/mac48-address.h" +#include "ns3/pointer.h" +#include "ns3/queue.h" +#include "ns3/simulator.h" +#include "ns3/trace-source-accessor.h" +#include "ns3/uinteger.h" +#include "ns3/channel.h" +#include "ns3/data-rate.h" +#include "ns3/nstime.h" +#include "ns3/ptr.h" +#include "ns3/traced-callback.h" + +#include "ns3/log.h" +#include "ns3/packet.h" +#include "ns3/simulator.h" +#include "ns3/trace-source-accessor.h" + +#include "frr_queue_base.h" + +#include + +#include + +#define STRINGIFY_TYPE_ALIAS(alias) typeid(alias).name() + +namespace ns3 +{ + +NS_LOG_COMPONENT_DEFINE("FRRQueue"); + +template +class PointToPointFRRChannel; + +class ErrorModel; + +template +class PointToPointFRRNetDevice : public NetDevice +{ + public: + static TypeId GetTypeId(); + + PointToPointFRRNetDevice(); + + ~PointToPointFRRNetDevice() override; + + // Delete copy constructor and assignment operator to avoid misuse + PointToPointFRRNetDevice& + operator=(const PointToPointFRRNetDevice&) = delete; + PointToPointFRRNetDevice(const PointToPointFRRNetDevice&) = + delete; + + void SetDataRate(DataRate bps); + + void SetInterframeGap(Time t); + + bool Attach(Ptr> ch); + + void SetQueue(Ptr> queue); + + Ptr> GetQueue() const; + + void SetReceiveErrorModel(Ptr em); + + void Receive(Ptr p); + + // The remaining methods are documented in ns3::NetDevice* + + void SetIfIndex(const uint32_t index) override; + uint32_t GetIfIndex() const override; + + Ptr GetChannel() const override; + + void SetAddress(Address address) override; + Address GetAddress() const override; + + bool SetMtu(const uint16_t mtu) override; + uint16_t GetMtu() const override; + + bool IsLinkUp() const override; + + void AddLinkChangeCallback(Callback callback) override; + + bool IsBroadcast() const override; + Address GetBroadcast() const override; + + bool IsMulticast() const override; + Address GetMulticast(Ipv4Address multicastGroup) const override; + + bool IsPointToPoint() const override; + bool IsBridge() const override; + + bool Send(Ptr packet, const Address& dest, + uint16_t protocolNumber) override; + bool SendFrom(Ptr packet, const Address& source, + const Address& dest, uint16_t protocolNumber) override; + + Ptr GetNode() const override; + void SetNode(Ptr node) override; + + bool NeedsArp() const override; + + void SetReceiveCallback(NetDevice::ReceiveCallback cb) override; + + Address GetMulticast(Ipv6Address addr) const override; + + void SetPromiscReceiveCallback(PromiscReceiveCallback cb) override; + bool SupportsSendFrom() const override; + + bool isCongested(); + + void addAlternateTarget(Ptr> device); + + static std::string makeNetDeviceString(); + static const std::string& getNetDeviceString(); + + protected: + void DoMpiReceive(Ptr p); + + private: + void DoDispose() override; + + Address GetRemote() const; + + void AddHeader(Ptr p, uint16_t protocolNumber); + + bool ProcessHeader(Ptr p, uint16_t& param); + + bool TransmitStart(Ptr p); + + void TransmitComplete(); + + void NotifyLinkUp(); + + enum TxMachineState { READY, BUSY }; + + TxMachineState m_txMachineState; + + DataRate m_bps; + + Time m_tInterframeGap; + + Ptr> m_channel; + + Ptr> m_queue; + + Ptr m_receiveErrorModel; + + TracedCallback> m_macTxTrace; + + TracedCallback> m_macTxDropTrace; + + TracedCallback> m_macPromiscRxTrace; + + TracedCallback> m_macRxTrace; + + TracedCallback> m_macRxDropTrace; + + TracedCallback> m_phyTxBeginTrace; + + TracedCallback> m_phyTxEndTrace; + + TracedCallback> m_phyTxDropTrace; + + TracedCallback> m_phyRxBeginTrace; + + TracedCallback> m_phyRxEndTrace; + + TracedCallback> m_phyRxDropTrace; + + TracedCallback> m_snifferTrace; + + TracedCallback> m_promiscSnifferTrace; + + Ptr m_node; + Mac48Address m_address; + NetDevice::ReceiveCallback m_rxCallback; + NetDevice::PromiscReceiveCallback m_promiscCallback; + // (promisc data) + uint32_t m_ifIndex; + bool m_linkUp; + TracedCallback<> m_linkChangeCallbacks; + + static const uint16_t DEFAULT_MTU = 1500; + + uint32_t m_mtu; + + Ptr m_currentPkt; + + FRR_POLICY m_frr_policy; + + static uint16_t PppToEther(uint16_t protocol); + + static uint16_t EtherToPpp(uint16_t protocol); +}; + +class Packet; + +template +class PointToPointFRRChannel : public Channel +{ + public: + static TypeId GetTypeId(); + + PointToPointFRRChannel(); + + void Attach(Ptr> device); + + virtual bool TransmitStart(Ptr p, + Ptr> src, + Time txTime); + + std::size_t GetNDevices() const override; + + Ptr> + GetPointToPointDevice(std::size_t i) const; + + Ptr GetDevice(std::size_t i) const override; + + static std::string makeChannelString(); + static const std::string& getChannelString(); + + protected: + Time GetDelay() const; + + bool IsInitialized() const; + + Ptr> GetSource(uint32_t i) const; + + Ptr> GetDestination(uint32_t i) const; + + typedef void (*TxRxAnimationCallback)(Ptr packet, + Ptr txDevice, + Ptr rxDevice, + Time duration, Time lastBitTime); + + private: + static const std::size_t N_DEVICES = 2; + + Time m_delay; + std::size_t m_nDevices; + + TracedCallback, // Packet being transmitted + Ptr, // Transmitting NetDevice + Ptr, // Receiving NetDevice + Time, // Amount of time to transmit the pkt + Time // Last bit receive time (relative to now) + > + m_txrxPointToPoint; + + enum WireState { INITIALIZING, IDLE, TRANSMITTING, PROPAGATING }; + + class Link + { + public: + Link() = default; + + WireState m_state{INITIALIZING}; + Ptr> m_src; + Ptr> m_dst; + }; + + Link m_link[N_DEVICES]; +}; + +template +TypeId PointToPointFRRChannel::GetTypeId() +{ + static TypeId tid = + TypeId(getChannelString()) + .SetParent() + .SetGroupName("PointToPoint") + .AddConstructor>() + .AddAttribute( + "Delay", "Propagation delay through the channel", + TimeValue(Seconds(0)), + MakeTimeAccessor(&PointToPointFRRChannel::m_delay), + MakeTimeChecker()) + .AddTraceSource( + "TxRxPointToPoint", + "Trace source indicating transmission of packet " + "from the PointToPointFRRChannel, used by the Animation " + "interface.", + MakeTraceSourceAccessor( + &PointToPointFRRChannel::m_txrxPointToPoint), + getChannelString() + "::TxRxAnimationCallback"); + return tid; +} + +// +// By default, you get a channel that +// has an "infitely" fast transmission speed and zero delay. +template +PointToPointFRRChannel::PointToPointFRRChannel() + : Channel(), m_delay(Seconds(0.)), m_nDevices(0) +{ + NS_LOG_FUNCTION_NOARGS(); +} + +template +void PointToPointFRRChannel::Attach( + Ptr> device) +{ + NS_LOG_FUNCTION(this << device); + NS_ASSERT_MSG(m_nDevices < N_DEVICES, "Only two devices permitted"); + NS_ASSERT(device); + + m_link[m_nDevices++].m_src = device; + // + // If we have both devices connected to the channel, then finish introducing + // the two halves and set the links to IDLE. + // + if (m_nDevices == N_DEVICES) { + m_link[0].m_dst = m_link[1].m_src; + m_link[1].m_dst = m_link[0].m_src; + m_link[0].m_state = IDLE; + m_link[1].m_state = IDLE; + } +} + +template +bool PointToPointFRRChannel::TransmitStart( + Ptr p, Ptr> src, + Time txTime) +{ + NS_LOG_FUNCTION(this << p << src); + NS_LOG_LOGIC("UID is " << p->GetUid() << ")"); + + NS_ASSERT(m_link[0].m_state != INITIALIZING); + NS_ASSERT(m_link[1].m_state != INITIALIZING); + + uint32_t wire = src == m_link[0].m_src ? 0 : 1; + + Simulator::ScheduleWithContext( + m_link[wire].m_dst->GetNode()->GetId(), txTime + m_delay, + &PointToPointFRRNetDevice::Receive, m_link[wire].m_dst, + p->Copy()); + + // Call the tx anim callback on the net device + m_txrxPointToPoint(p, src, m_link[wire].m_dst, txTime, txTime + m_delay); + return true; +} + +template +std::size_t PointToPointFRRChannel::GetNDevices() const +{ + NS_LOG_FUNCTION_NOARGS(); + return m_nDevices; +} + +template +Ptr> +PointToPointFRRChannel::GetPointToPointDevice(std::size_t i) const +{ + NS_LOG_FUNCTION_NOARGS(); + NS_ASSERT(i < 2); + return m_link[i].m_src; +} + +template +Ptr +PointToPointFRRChannel::GetDevice(std::size_t i) const +{ + NS_LOG_FUNCTION_NOARGS(); + return GetPointToPointDevice(i); +} + +template +Time PointToPointFRRChannel::GetDelay() const +{ + return m_delay; +} + +template +Ptr> +PointToPointFRRChannel::GetSource(uint32_t i) const +{ + return m_link[i].m_src; +} + +template +Ptr> +PointToPointFRRChannel::GetDestination(uint32_t i) const +{ + return m_link[i].m_dst; +} + +template +bool PointToPointFRRChannel::IsInitialized() const +{ + NS_ASSERT(m_link[0].m_state != INITIALIZING); + NS_ASSERT(m_link[1].m_state != INITIALIZING); + return true; +} + +template +TypeId PointToPointFRRNetDevice::GetTypeId() +{ + static TypeId tid = + TypeId(getNetDeviceString()) + .SetParent() + .SetGroupName("PointToPoint") + .AddConstructor>() + .AddAttribute("Mtu", "The MAC-level Maximum Transmission Unit", + UintegerValue(DEFAULT_MTU), + MakeUintegerAccessor( + &PointToPointFRRNetDevice::SetMtu, + &PointToPointFRRNetDevice::GetMtu), + MakeUintegerChecker()) + .AddAttribute("Address", "The MAC address of this device.", + Mac48AddressValue(Mac48Address("ff:ff:ff:ff:ff:ff")), + MakeMac48AddressAccessor( + &PointToPointFRRNetDevice::m_address), + MakeMac48AddressChecker()) + .AddAttribute("DataRate", + "The default data rate for point to point links", + DataRateValue(DataRate("32768b/s")), + MakeDataRateAccessor( + &PointToPointFRRNetDevice::m_bps), + MakeDataRateChecker()) + .AddAttribute( + "ReceiveErrorModel", + "The receiver error model used to simulate packet loss", + PointerValue(), + MakePointerAccessor( + &PointToPointFRRNetDevice::m_receiveErrorModel), + MakePointerChecker()) + .AddAttribute( + "InterframeGap", + "The time to wait between packet (frame) transmissions", + TimeValue(Seconds(0.0)), + MakeTimeAccessor( + &PointToPointFRRNetDevice::m_tInterframeGap), + MakeTimeChecker()) + + // + // Transmit queueing discipline for the device which includes its + // own set of trace hooks. + // + .AddAttribute("TxQueue", + "A queue to use as the transmit queue in the device.", + PointerValue(), + MakePointerAccessor( + &PointToPointFRRNetDevice::m_queue), + MakePointerChecker>()) + + // + // Trace sources at the "top" of the net device, where packets + // transition to/from higher layers. + // + .AddTraceSource( + "MacTx", + "Trace source indicating a packet has arrived " + "for transmission by this device", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_macTxTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource( + "MacTxDrop", + "Trace source indicating a packet has been dropped " + "by the device before transmission", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_macTxDropTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource( + "MacPromiscRx", + "A packet has been received by this device, " + "has been passed up from the physical layer " + "and is being forwarded up the local protocol stack. " + "This is a promiscuous trace,", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_macPromiscRxTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource( + "MacRx", + "A packet has been received by this device, " + "has been passed up from the physical layer " + "and is being forwarded up the local protocol stack. " + "This is a non-promiscuous trace,", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_macRxTrace), + "ns3::Packet::TracedCallback") +#if 0 + // Not currently implemented for this device + .AddTraceSource ("MacRxDrop", + "Trace source indicating a packet was dropped " + "before being forwarded up the stack", + MakeTraceSourceAccessor (&PointToPointFRRNetDevice::m_macRxDropTrace), + "ns3::Packet::TracedCallback") +#endif + // + // Trace sources at the "bottom" of the net device, where packets + // transition to/from the channel. + // + .AddTraceSource( + "PhyTxBegin", + "Trace source indicating a packet has begun " + "transmitting over the channel", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_phyTxBeginTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource( + "PhyTxEnd", + "Trace source indicating a packet has been " + "completely transmitted over the channel", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_phyTxEndTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource( + "PhyTxDrop", + "Trace source indicating a packet has been " + "dropped by the device during transmission", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_phyTxDropTrace), + "ns3::Packet::TracedCallback") +#if 0 + // Not currently implemented for this device + .AddTraceSource ("PhyRxBegin", + "Trace source indicating a packet has begun " + "being received by the device", + MakeTraceSourceAccessor (&PointToPointFRRNetDevice::m_phyRxBeginTrace), + "ns3::Packet::TracedCallback") +#endif + .AddTraceSource( + "PhyRxEnd", + "Trace source indicating a packet has been " + "completely received by the device", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_phyRxEndTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource( + "PhyRxDrop", + "Trace source indicating a packet has been " + "dropped by the device during reception", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_phyRxDropTrace), + "ns3::Packet::TracedCallback") + + // + // Trace sources designed to simulate a packet sniffer facility + // (tcpdump). Note that there is really no difference between + // promiscuous and non-promiscuous traces in a point-to-point link. + // + .AddTraceSource( + "Sniffer", + "Trace source simulating a non-promiscuous packet sniffer " + "attached to the device", + MakeTraceSourceAccessor( + &PointToPointFRRNetDevice::m_snifferTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource( + "PromiscSniffer", + "Trace source simulating a promiscuous packet sniffer " + "attached to the device", + MakeTraceSourceAccessor(&PointToPointFRRNetDevice< + FRR_POLICY>::m_promiscSnifferTrace), + "ns3::Packet::TracedCallback"); + return tid; +} + +template +PointToPointFRRNetDevice::PointToPointFRRNetDevice() + : m_txMachineState(READY), m_channel(nullptr), m_linkUp(false), + m_currentPkt(nullptr) +{ + NS_LOG_FUNCTION(this); +} + +template +PointToPointFRRNetDevice::~PointToPointFRRNetDevice() +{ + NS_LOG_FUNCTION(this); +} + +template +void PointToPointFRRNetDevice::AddHeader(Ptr p, + uint16_t protocolNumber) +{ + NS_LOG_FUNCTION(this << p << protocolNumber); + PppHeader ppp; + ppp.SetProtocol(EtherToPpp(protocolNumber)); + p->AddHeader(ppp); +} + +template +bool PointToPointFRRNetDevice::ProcessHeader(Ptr p, + uint16_t& param) +{ + NS_LOG_FUNCTION(this << p << param); + PppHeader ppp; + p->RemoveHeader(ppp); + param = PppToEther(ppp.GetProtocol()); + return true; +} + +template +void PointToPointFRRNetDevice::DoDispose() +{ + NS_LOG_FUNCTION(this); + m_node = nullptr; + m_channel = nullptr; + m_receiveErrorModel = nullptr; + m_currentPkt = nullptr; + m_queue = nullptr; + NetDevice::DoDispose(); +} + +template +void PointToPointFRRNetDevice::SetDataRate(DataRate bps) +{ + NS_LOG_FUNCTION(this); + m_bps = bps; +} + +template +void PointToPointFRRNetDevice::SetInterframeGap(Time t) +{ + NS_LOG_FUNCTION(this << t.As(Time::S)); + m_tInterframeGap = t; +} + +template +bool PointToPointFRRNetDevice::TransmitStart(Ptr p) +{ + NS_LOG_FUNCTION(this << p); + NS_LOG_LOGIC("UID is " << p->GetUid() << ")"); + + // + // This function is called to start the process of transmitting a packet. + // We need to tell the channel that we've started wiggling the wire and + // schedule an event that will be executed when the transmission is + // complete. + // + NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit"); + m_txMachineState = BUSY; + m_currentPkt = p; + m_phyTxBeginTrace(m_currentPkt); + + Time txTime = m_bps.CalculateBytesTxTime(p->GetSize()); + Time txCompleteTime = txTime + m_tInterframeGap; + + NS_LOG_LOGIC("Schedule TransmitCompleteEvent in " + << txCompleteTime.As(Time::S)); + Simulator::Schedule(txCompleteTime, + &PointToPointFRRNetDevice::TransmitComplete, + this); + + bool result = m_channel->TransmitStart(p, this, txTime); + if (!result) { + m_phyTxDropTrace(p); + } + return result; +} + +template +void PointToPointFRRNetDevice::TransmitComplete() +{ + NS_LOG_FUNCTION(this); + + // + // This function is called to when we're all done transmitting a packet. + // We try and pull another packet off of the transmit queue. If the queue + // is empty, we are done, otherwise we need to start transmitting the + // next packet. + // + NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting"); + m_txMachineState = READY; + + NS_ASSERT_MSG( + m_currentPkt, + "PointToPointFRRNetDevice::TransmitComplete(): m_currentPkt zero"); + + m_phyTxEndTrace(m_currentPkt); + m_currentPkt = nullptr; + + Ptr p = m_queue->Dequeue(); + if (!p) { + NS_LOG_LOGIC("No pending packets in device queue after tx complete"); + return; + } + + // + // Got another packet off of the queue, so start the transmit process again. + // + m_snifferTrace(p); + m_promiscSnifferTrace(p); + TransmitStart(p); +} + +template +bool PointToPointFRRNetDevice::Attach( + Ptr> ch) +{ + NS_LOG_FUNCTION(this << &ch); + + m_channel = ch; + + m_channel->Attach(this); + + // + // This device is up whenever it is attached to a channel. A better plan + // would be to have the link come up when both devices are attached, but + // this is not done for now. + // + NotifyLinkUp(); + return true; +} + +template +void PointToPointFRRNetDevice::SetQueue(Ptr> q) +{ + NS_LOG_FUNCTION(this << q); + m_queue = q; +} + +template +void PointToPointFRRNetDevice::SetReceiveErrorModel( + Ptr em) +{ + NS_LOG_FUNCTION(this << em); + m_receiveErrorModel = em; +} + +template +void PointToPointFRRNetDevice::Receive(Ptr packet) +{ + NS_LOG_FUNCTION(this << packet); + uint16_t protocol = 0; + + if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt(packet)) { + // + // If we have an error model and it indicates that it is time to lose a + // corrupted packet, don't forward this packet up, let it go. + // + m_phyRxDropTrace(packet); + } else { + // + // Hit the trace hooks. All of these hooks are in the same place in + // this device because it is so simple, but this is not usually the case + // in more complicated devices. + // + m_snifferTrace(packet); + m_promiscSnifferTrace(packet); + m_phyRxEndTrace(packet); + + // + // Trace sinks will expect complete packets, not packets without some of + // the headers. + // + Ptr originalPacket = packet->Copy(); + + // + // Strip off the point-to-point protocol header and forward this packet + // up the protocol stack. Since this is a simple point-to-point link, + // there is no difference in what the promisc callback sees and what the + // normal receive callback sees. + // + ProcessHeader(packet, protocol); + + if (!m_promiscCallback.IsNull()) { + m_macPromiscRxTrace(originalPacket); + m_promiscCallback(this, packet, protocol, GetRemote(), GetAddress(), + NetDevice::PACKET_HOST); + } + + m_macRxTrace(originalPacket); + m_rxCallback(this, packet, protocol, GetRemote()); + } +} + +template +Ptr> PointToPointFRRNetDevice::GetQueue() const +{ + NS_LOG_FUNCTION(this); + return m_queue; +} + +template +void PointToPointFRRNetDevice::NotifyLinkUp() +{ + NS_LOG_FUNCTION(this); + m_linkUp = true; + m_linkChangeCallbacks(); +} + +template +void PointToPointFRRNetDevice::SetIfIndex(const uint32_t index) +{ + NS_LOG_FUNCTION(this); + m_ifIndex = index; +} + +template +uint32_t PointToPointFRRNetDevice::GetIfIndex() const +{ + return m_ifIndex; +} + +template +Ptr PointToPointFRRNetDevice::GetChannel() const +{ + return m_channel; +} + +// +// This is a point-to-point device, so we really don't need any kind of address +// information. However, the base class NetDevice wants us to define the +// methods to get and set the address. Rather than be rude and assert, we let +// clients get and set the address, but simply ignore them. + +template +void PointToPointFRRNetDevice::SetAddress(Address address) +{ + NS_LOG_FUNCTION(this << address); + m_address = Mac48Address::ConvertFrom(address); +} + +template +Address PointToPointFRRNetDevice::GetAddress() const +{ + return m_address; +} + +template +bool PointToPointFRRNetDevice::IsLinkUp() const +{ + NS_LOG_FUNCTION(this); + return m_linkUp; +} + +template +void PointToPointFRRNetDevice::AddLinkChangeCallback( + Callback callback) +{ + NS_LOG_FUNCTION(this); + m_linkChangeCallbacks.ConnectWithoutContext(callback); +} + +// +// This is a point-to-point device, so every transmission is a broadcast to +// all of the devices on the network. +// +template +bool PointToPointFRRNetDevice::IsBroadcast() const +{ + NS_LOG_FUNCTION(this); + return true; +} + +// +// We don't really need any addressing information since this is a +// point-to-point device. The base class NetDevice wants us to return a +// broadcast address, so we make up something reasonable. +// +template +Address PointToPointFRRNetDevice::GetBroadcast() const +{ + NS_LOG_FUNCTION(this); + return Mac48Address::GetBroadcast(); +} + +template +bool PointToPointFRRNetDevice::IsMulticast() const +{ + NS_LOG_FUNCTION(this); + return true; +} + +template +Address PointToPointFRRNetDevice::GetMulticast( + Ipv4Address multicastGroup) const +{ + NS_LOG_FUNCTION(this); + return Mac48Address("01:00:5e:00:00:00"); +} + +template +Address +PointToPointFRRNetDevice::GetMulticast(Ipv6Address addr) const +{ + NS_LOG_FUNCTION(this << addr); + return Mac48Address("33:33:00:00:00:00"); +} + +template +bool PointToPointFRRNetDevice::IsPointToPoint() const +{ + NS_LOG_FUNCTION(this); + return true; +} + +template +bool PointToPointFRRNetDevice::IsBridge() const +{ + NS_LOG_FUNCTION(this); + return false; +} + +template +void PointToPointFRRNetDevice::addAlternateTarget( + Ptr> device) +{ + m_frr_policy.addAlternateTargets(device); +} + +template +bool PointToPointFRRNetDevice::isCongested() +{ + return dynamic_cast(PeekPointer(m_queue))->isCongested(); +} + +template +bool PointToPointFRRNetDevice::Send(Ptr packet, + const Address& dest, + uint16_t protocolNumber) +{ + NS_LOG_FUNCTION(this << packet << dest << protocolNumber); + NS_LOG_LOGIC("p=" << packet << ", dest=" << &dest); + NS_LOG_LOGIC("UID is " << packet->GetUid()); + + // + // If IsLinkUp() is false it means there is no channel to send any packet + // over so we just hit the drop trace on the packet and return an error. + // + if (!IsLinkUp()) { + m_macTxDropTrace(packet); + return false; + } + + if (isCongested()) { + NS_LOG_LOGIC("Device is congested, rerouting"); + return m_frr_policy.reroute(packet, dest, protocolNumber); + } + NS_LOG_LOGIC("Device is not congested, sending packet normally"); + // + // Stick a point to point protocol header on the packet in preparation for + // shoving it out the door. + // + + AddHeader(packet, protocolNumber); + m_macTxTrace(packet); + + // + // We should enqueue and dequeue the packet to hit the tracing hooks. + // + if (m_queue->Enqueue(packet)) { + // + // If the channel is ready for transition we send the packet right now + // + if (m_txMachineState == READY) { + packet = m_queue->Dequeue(); + m_snifferTrace(packet); + m_promiscSnifferTrace(packet); + bool ret = TransmitStart(packet); + return ret; + } + return true; + } + + // Enqueue may fail (overflow) + + m_macTxDropTrace(packet); + return false; +} + +template +bool PointToPointFRRNetDevice::SendFrom(Ptr packet, + const Address& source, + const Address& dest, + uint16_t protocolNumber) +{ + NS_LOG_FUNCTION(this << packet << source << dest << protocolNumber); + return false; +} + +template +Ptr PointToPointFRRNetDevice::GetNode() const +{ + return m_node; +} + +template +void PointToPointFRRNetDevice::SetNode(Ptr node) +{ + NS_LOG_FUNCTION(this); + m_node = node; +} + +template +bool PointToPointFRRNetDevice::NeedsArp() const +{ + NS_LOG_FUNCTION(this); + return false; +} + +template +void PointToPointFRRNetDevice::SetReceiveCallback( + NetDevice::ReceiveCallback cb) +{ + m_rxCallback = cb; +} + +template +void PointToPointFRRNetDevice::SetPromiscReceiveCallback( + NetDevice::PromiscReceiveCallback cb) +{ + m_promiscCallback = cb; +} + +template +bool PointToPointFRRNetDevice::SupportsSendFrom() const +{ + NS_LOG_FUNCTION(this); + return false; +} + +template +void PointToPointFRRNetDevice::DoMpiReceive(Ptr p) +{ + NS_LOG_FUNCTION(this << p); + Receive(p); +} + +template +Address PointToPointFRRNetDevice::GetRemote() const +{ + NS_LOG_FUNCTION(this); + NS_ASSERT(m_channel->GetNDevices() == 2); + for (std::size_t i = 0; i < m_channel->GetNDevices(); ++i) { + Ptr tmp = m_channel->GetDevice(i); + if (tmp != this) { + return tmp->GetAddress(); + } + } + NS_ASSERT(false); + // quiet compiler. + return Address(); +} + +template +bool PointToPointFRRNetDevice::SetMtu(uint16_t mtu) +{ + NS_LOG_FUNCTION(this << mtu); + m_mtu = mtu; + return true; +} + +template +uint16_t PointToPointFRRNetDevice::GetMtu() const +{ + NS_LOG_FUNCTION(this); + return m_mtu; +} + +template +uint16_t PointToPointFRRNetDevice::PppToEther(uint16_t proto) +{ + NS_LOG_FUNCTION_NOARGS(); + switch (proto) { + case 0x0021: return 0x0800; // IPv4 + case 0x0057: return 0x86DD; // IPv6 + default: NS_ASSERT_MSG(false, "PPP Protocol number not defined!"); + } + return 0; +} + +template +uint16_t PointToPointFRRNetDevice::EtherToPpp(uint16_t proto) +{ + NS_LOG_FUNCTION_NOARGS(); + switch (proto) { + case 0x0800: return 0x0021; // IPv4 + case 0x86DD: return 0x0057; // IPv6 + default: NS_ASSERT_MSG(false, "PPP Protocol number not defined!"); + } + return 0; +} + +template +std::string PointToPointFRRChannel::makeChannelString() +{ + using ChannelType = PointToPointFRRChannel; + int status; + char* demangled = abi::__cxa_demangle(STRINGIFY_TYPE_ALIAS(ChannelType), + nullptr, nullptr, &status); + std::string result = (status == 0 && demangled != nullptr) + ? demangled + : STRINGIFY_TYPE_ALIAS(ChannelType); + free(demangled); + return result; +} + +template +const std::string& PointToPointFRRChannel::getChannelString() +{ + const static std::string result = + PointToPointFRRChannel::makeChannelString(); + return result; +} + +template +std::string PointToPointFRRNetDevice::makeNetDeviceString() +{ + using NetDeviceType = PointToPointFRRNetDevice; + int status; + char* demangled = abi::__cxa_demangle(STRINGIFY_TYPE_ALIAS(NetDeviceType), + nullptr, nullptr, &status); + std::string result = (status == 0 && demangled != nullptr) + ? demangled + : STRINGIFY_TYPE_ALIAS(NetDeviceType); + free(demangled); + return result; +} + +template +const std::string& PointToPointFRRNetDevice::getNetDeviceString() +{ + const static std::string result = + PointToPointFRRNetDevice::makeNetDeviceString(); + return result; +} + +} // namespace ns3 + +#endif /* POINT_TO_POINT_FRR_NET_DEVICE_H */ From fe3ea448b552735b4844cddb4e32d34ccaab3e57 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Thu, 14 Mar 2024 02:43:27 +0000 Subject: [PATCH 24/28] :sparkles: add custom p2p helper for point-to-point frr net device --- libs/point_to_point_frr_helper.h | 387 +++++++++++++++++++++++++++++++ 1 file changed, 387 insertions(+) create mode 100644 libs/point_to_point_frr_helper.h diff --git a/libs/point_to_point_frr_helper.h b/libs/point_to_point_frr_helper.h new file mode 100644 index 00000000..9d8a6259 --- /dev/null +++ b/libs/point_to_point_frr_helper.h @@ -0,0 +1,387 @@ +#ifndef POINT_TO_POINT_FRR_HELPER_H +#define POINT_TO_POINT_FRR_HELPER_H + +#include "ns3/abort.h" +#include "ns3/config.h" +#include "ns3/log.h" +#include "ns3/names.h" +#include "ns3/net-device-queue-interface.h" +#include "ns3/packet.h" +#include "ns3/point-to-point-channel.h" +#include "point_to_point_frr_net_device.h" +#include "ns3/simulator.h" + +#include "ns3/trace-helper.h" +#include "ns3/net-device-container.h" +#include "ns3/node-container.h" +#include "ns3/object-factory.h" +#include "ns3/queue.h" +#include "ns3/trace-helper.h" + +#include + +namespace ns3 +{ + +class NetDevice; +class Node; + +template +class PointToPointFRRHelper : public PcapHelperForDevice, + public AsciiTraceHelperForDevice +{ + public: + PointToPointFRRHelper(); + + ~PointToPointFRRHelper() override + { + } + + template + void SetQueue(std::string type, Ts&&... args); + + void SetDeviceAttribute(std::string name, const AttributeValue& value); + + void SetChannelAttribute(std::string name, const AttributeValue& value); + + void DisableFlowControl(); + + NetDeviceContainer Install(NodeContainer c); + + NetDeviceContainer Install(Ptr a, Ptr b); + + NetDeviceContainer Install(Ptr a, std::string bName); + + NetDeviceContainer Install(std::string aName, Ptr b); + + NetDeviceContainer Install(std::string aNode, std::string bNode); + + private: + void EnablePcapInternal(std::string prefix, Ptr nd, + bool promiscuous, bool explicitFilename) override; + + void EnableAsciiInternal(Ptr stream, + std::string prefix, Ptr nd, + bool explicitFilename) override; + + ObjectFactory m_queueFactory; + ObjectFactory m_channelFactory; + ObjectFactory m_deviceFactory; + bool m_enableFlowControl; +}; + +/*************************************************************** + * Implementation of the templates declared above. + ***************************************************************/ + +template +template +void PointToPointFRRHelper::SetQueue(std::string type, Ts&&... args) +{ + QueueBase::AppendItemTypeIfNotPresent(type, "Packet"); + + m_queueFactory.SetTypeId(type); + m_queueFactory.Set(std::forward(args)...); +} + +template +PointToPointFRRHelper::PointToPointFRRHelper() +{ + m_queueFactory.SetTypeId("ns3::DropTailQueue"); + m_deviceFactory.SetTypeId( + ns3::PointToPointFRRNetDevice::getNetDeviceString()); + m_channelFactory.SetTypeId( + ns3::PointToPointFRRChannel::getChannelString()); + m_enableFlowControl = true; +} + +template +void PointToPointFRRHelper::SetDeviceAttribute( + std::string n1, const AttributeValue& v1) +{ + m_deviceFactory.Set(n1, v1); +} + +template +void PointToPointFRRHelper::SetChannelAttribute( + std::string n1, const AttributeValue& v1) +{ + m_channelFactory.Set(n1, v1); +} + +template +void PointToPointFRRHelper::DisableFlowControl() +{ + m_enableFlowControl = false; +} + +template +void PointToPointFRRHelper::EnablePcapInternal( + std::string prefix, Ptr nd, bool promiscuous, + bool explicitFilename) +{ + // + // All of the Pcap enable functions vector through here including the ones + // that are wandering through all of devices on perhaps all of the nodes in + // the system. We can only deal with devices of type + // PointToPointFRRNetDevice. + // + Ptr> device = + nd->GetObject>(); + if (!device) { + NS_LOG_INFO("Device " << device + << " not of type ns3::PointToPointFRRNetDevice"); + return; + } + + PcapHelper pcapHelper; + + std::string filename; + if (explicitFilename) { + filename = prefix; + } else { + filename = pcapHelper.GetFilenameFromDevice(prefix, device); + } + + Ptr file = + pcapHelper.CreateFile(filename, std::ios::out, PcapHelper::DLT_PPP); + pcapHelper.HookDefaultSink>( + device, "PromiscSniffer", file); +} + +template +void PointToPointFRRHelper::EnableAsciiInternal( + Ptr stream, std::string prefix, Ptr nd, + bool explicitFilename) +{ + // + // All of the ascii enable functions vector through here including the ones + // that are wandering through all of devices on perhaps all of the nodes in + // the system. We can only deal with devices of type + // PointToPointFRRNetDevice. + // + Ptr> device = + nd->GetObject>(); + if (!device) { + NS_LOG_INFO("Device " << device + << " not of type ns3::PointToPointFRRNetDevice"); + return; + } + + // + // Our default trace sinks are going to use packet printing, so we have to + // make sure that is turned on. + // + Packet::EnablePrinting(); + + // + // If we are not provided an OutputStreamWrapper, we are expected to create + // one using the usual trace filename conventions and do a + // Hook*WithoutContext since there will be one file per context and + // therefore the context would be redundant. + // + if (!stream) { + // + // Set up an output stream object to deal with private ofstream copy + // constructor and lifetime issues. Let the helper decide the actual + // name of the file given the prefix. + // + AsciiTraceHelper asciiTraceHelper; + + std::string filename; + if (explicitFilename) { + filename = prefix; + } else { + filename = asciiTraceHelper.GetFilenameFromDevice(prefix, device); + } + + Ptr theStream = + asciiTraceHelper.CreateFileStream(filename); + + // + // The MacRx trace source provides our "r" event. + // + asciiTraceHelper.HookDefaultReceiveSinkWithoutContext< + PointToPointFRRNetDevice>(device, "MacRx", theStream); + + // + // The "+", '-', and 'd' events are driven by trace sources actually in + // the transmit queue. + // + Ptr> queue = device->GetQueue(); + asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext>( + queue, "Enqueue", theStream); + asciiTraceHelper.HookDefaultDropSinkWithoutContext>( + queue, "Drop", theStream); + asciiTraceHelper.HookDefaultDequeueSinkWithoutContext>( + queue, "Dequeue", theStream); + + // PhyRxDrop trace source for "d" event + asciiTraceHelper.HookDefaultDropSinkWithoutContext< + PointToPointFRRNetDevice>(device, "PhyRxDrop", + theStream); + + return; + } + + // + // If we are provided an OutputStreamWrapper, we are expected to use it, and + // to providd a context. We are free to come up with our own context if we + // want, and use the AsciiTraceHelper Hook*WithContext functions, but for + // compatibility and simplicity, we just use Config::Connect and let it deal + // with the context. + // + // Note that we are going to use the default trace sinks provided by the + // ascii trace helper. There is actually no AsciiTraceHelper in sight here, + // but the default trace sinks are actually publicly available static + // functions that are always there waiting for just such a case. + // + uint32_t nodeid = nd->GetNode()->GetId(); + uint32_t deviceid = nd->GetIfIndex(); + std::ostringstream oss; + + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid + << "/$ns3::PointToPointFRRNetDevice/MacRx"; + Config::Connect( + oss.str(), + MakeBoundCallback(&AsciiTraceHelper::DefaultReceiveSinkWithContext, + stream)); + + oss.str(""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid + << "/$ns3::PointToPointFRRNetDevice/TxQueue/Enqueue"; + Config::Connect( + oss.str(), + MakeBoundCallback(&AsciiTraceHelper::DefaultEnqueueSinkWithContext, + stream)); + + oss.str(""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid + << "/$ns3::PointToPointFRRNetDevice/TxQueue/Dequeue"; + Config::Connect( + oss.str(), + MakeBoundCallback(&AsciiTraceHelper::DefaultDequeueSinkWithContext, + stream)); + + oss.str(""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid + << "/$ns3::PointToPointFRRNetDevice/TxQueue/Drop"; + Config::Connect(oss.str(), + MakeBoundCallback( + &AsciiTraceHelper::DefaultDropSinkWithContext, stream)); + + oss.str(""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid + << "/$ns3::PointToPointFRRNetDevice/PhyRxDrop"; + Config::Connect(oss.str(), + MakeBoundCallback( + &AsciiTraceHelper::DefaultDropSinkWithContext, stream)); +} + +template +NetDeviceContainer PointToPointFRRHelper::Install(NodeContainer c) +{ + NS_ASSERT(c.GetN() == 2); + return Install(c.Get(0), c.Get(1)); +} + +template +NetDeviceContainer PointToPointFRRHelper::Install(Ptr a, + Ptr b) +{ + NetDeviceContainer container; + + Ptr> devA = + m_deviceFactory.Create>(); + devA->SetAddress(Mac48Address::Allocate()); + a->AddDevice(devA); + Ptr> queueA = m_queueFactory.Create>(); + devA->SetQueue(queueA); + Ptr> devB = + m_deviceFactory.Create>(); + devB->SetAddress(Mac48Address::Allocate()); + b->AddDevice(devB); + Ptr> queueB = m_queueFactory.Create>(); + devB->SetQueue(queueB); + if (m_enableFlowControl) { + // Aggregate NetDeviceQueueInterface objects + Ptr ndqiA = + CreateObject(); + ndqiA->GetTxQueue(0)->ConnectQueueTraces(queueA); + devA->AggregateObject(ndqiA); + Ptr ndqiB = + CreateObject(); + ndqiB->GetTxQueue(0)->ConnectQueueTraces(queueB); + devB->AggregateObject(ndqiB); + } + + Ptr> channel = nullptr; + + // If MPI is enabled, we need to see if both nodes have the same system id + // (rank), and the rank is the same as this instance. If both are true, + // use a normal p2p channel, otherwise use a remote channel +#ifdef NS3_MPI + bool useNormalChannel = true; + if (MpiInterface::IsEnabled()) { + uint32_t n1SystemId = a->GetSystemId(); + uint32_t n2SystemId = b->GetSystemId(); + uint32_t currSystemId = MpiInterface::GetSystemId(); + if (n1SystemId != currSystemId || n2SystemId != currSystemId) { + useNormalChannel = false; + } + } + if (useNormalChannel) { + m_channelFactory.SetTypeId("ns3::PointToPointFRRChannel"); + channel = m_channelFactory.Create>(); + } else { + m_channelFactory.SetTypeId("ns3::PointToPointRemoteChannel"); + channel = m_channelFactory.Create(); + Ptr mpiRecA = CreateObject(); + Ptr mpiRecB = CreateObject(); + mpiRecA->SetReceiveCallback( + MakeCallback(&PointToPointFRRNetDevice::Receive, devA)); + mpiRecB->SetReceiveCallback( + MakeCallback(&PointToPointFRRNetDevice::Receive, devB)); + devA->AggregateObject(mpiRecA); + devB->AggregateObject(mpiRecB); + } +#else + channel = m_channelFactory.Create>(); +#endif + + devA->Attach(channel); + devB->Attach(channel); + container.Add(devA); + container.Add(devB); + + return container; +} + +template +NetDeviceContainer PointToPointFRRHelper::Install(Ptr a, + std::string bName) +{ + Ptr b = Names::Find(bName); + return Install(a, b); +} + +template +NetDeviceContainer PointToPointFRRHelper::Install(std::string aName, + Ptr b) +{ + Ptr a = Names::Find(aName); + return Install(a, b); +} + +template +NetDeviceContainer PointToPointFRRHelper::Install(std::string aName, + std::string bName) +{ + Ptr a = Names::Find(aName); + Ptr b = Names::Find(bName); + return Install(a, b); +} + +} // namespace ns3 + +#endif From b68b109eb52aa3bc750aa6ee814eb54125d7e158 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Thu, 14 Mar 2024 02:43:51 +0000 Subject: [PATCH 25/28] :recycle: update policies to match changes --- libs/lfa_policy.h | 22 +++++++++++++++------- libs/random_congestion_policy.h | 28 +++++++++++++++++++--------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/libs/lfa_policy.h b/libs/lfa_policy.h index 3c59b4c7..296fe7f5 100644 --- a/libs/lfa_policy.h +++ b/libs/lfa_policy.h @@ -6,15 +6,18 @@ #include "ns3/queue.h" #include "ns3/packet.h" -#include "ns3/point-to-point-net-device.h" +#include "point_to_point_frr_net_device.h" namespace ns3 { +class LFAPolicy; + class LFAPolicy { private: - std::list> m_alternateTargets; + std::list>> + m_alternateTargets; public: LFAPolicy() = default; @@ -22,7 +25,8 @@ class LFAPolicy template void addAlternateTargets(DEVICES&&... devices); - ns3::Ptr selectAlternativeTarget(); + bool reroute(Ptr packet, const Address& dest, + uint16_t protocolNumber); }; template @@ -31,12 +35,16 @@ void LFAPolicy::addAlternateTargets(DEVICES&&... devices) (m_alternateTargets.push_back(std::forward(devices)), ...); } -ns3::Ptr LFAPolicy::selectAlternativeTarget() +bool LFAPolicy::reroute(Ptr packet, const Address& dest, + uint16_t protocolNumber) { - if (m_alternateTargets.empty()) { - return nullptr; + for (auto& target : m_alternateTargets) { + if (!target->isCongested()) { + target->Send(packet, dest, protocolNumber); + return true; + } } - return m_alternateTargets.front(); + return false; } } // namespace ns3 diff --git a/libs/random_congestion_policy.h b/libs/random_congestion_policy.h index 557fdd51..516e801c 100644 --- a/libs/random_congestion_policy.h +++ b/libs/random_congestion_policy.h @@ -9,19 +9,12 @@ class RandomCongestionPolicy static_assert(PERCENTAGE >= 0 && PERCENTAGE <= 100, "Percentage must be between 0 and 100"); - bool m_off; + bool m_off = false; public: RandomCongestionPolicy() = default; - template - bool isCongested(const CONTAINER& container) const - { - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(0, 100); - return !m_off && dis(gen) < PERCENTAGE; - } + bool isCongested(ns3::Queue* queue) const; void turnOff() { @@ -29,4 +22,21 @@ class RandomCongestionPolicy } }; +template +bool RandomCongestionPolicy::isCongested( + ns3::Queue* queue) const +{ + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, 100); + return !m_off && dis(gen) < PERCENTAGE; +} + +template <> +bool RandomCongestionPolicy<100>::isCongested( + ns3::Queue* queue) const +{ + return !m_off; +} + #endif From c15b511ad116d70282cb7ff96ccbb05da09ec6fd Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Thu, 14 Mar 2024 02:44:11 +0000 Subject: [PATCH 26/28] :recycle: update scripts to reflect the changes --- src/lfa.cc | 20 ++++++++++++-------- src/lfa_random.cc | 33 ++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/lfa.cc b/src/lfa.cc index c4dc3b24..f2382f46 100644 --- a/src/lfa.cc +++ b/src/lfa.cc @@ -11,24 +11,28 @@ #include "../libs/dummy_congestion_policy.h" #include "../libs/modulo_congestion_policy.h" #include "../libs/lfa_policy.h" +#include "../libs/point_to_point_frr_helper.h" using namespace ns3; NS_LOG_COMPONENT_DEFINE("CongestionFastReRoute"); -// place the policies for FRR here using CongestionPolicy = ModuloCongestionPolicy<2>; - +// using CongestionPolicy = BasicCongestionPolicy<50>; using FRRPolicy = LFAPolicy; -using SimulationQueue = FRRQueue; +using SimulationQueue = FRRQueue; +using FRRNetDevice = PointToPointFRRNetDevice; +using FRRChannel = PointToPointFRRChannel; NS_OBJECT_ENSURE_REGISTERED(SimulationQueue); +NS_OBJECT_ENSURE_REGISTERED(FRRChannel); +NS_OBJECT_ENSURE_REGISTERED(FRRNetDevice); template -Ptr getDevice(const NetDeviceContainer& devices) +Ptr getDevice(const NetDeviceContainer& devices) { - return devices.Get(INDEX)->GetObject(); + return devices.Get(INDEX)->GetObject(); } template @@ -39,9 +43,9 @@ Ptr getQueue(const NetDeviceContainer& devices) template void setAlternateTarget(const NetDeviceContainer& devices, - Ptr target) + Ptr target) { - getQueue(devices)->addAlternateTargets(target); + getDevice(devices)->addAlternateTarget(target); } int main(int argc, char* argv[]) @@ -54,7 +58,7 @@ int main(int argc, char* argv[]) stack.Install(nodes); // Configure PointToPoint links - PointToPointHelper p2p; + PointToPointFRRHelper p2p; p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps")); p2p.SetChannelAttribute("Delay", StringValue("1ms")); diff --git a/src/lfa_random.cc b/src/lfa_random.cc index a7287394..519bb9af 100644 --- a/src/lfa_random.cc +++ b/src/lfa_random.cc @@ -12,13 +12,17 @@ #include "../libs/modulo_congestion_policy.h" #include "../libs/lfa_policy.h" #include "../libs/random_congestion_policy.h" +#include "../libs/point_to_point_frr_helper.h" using namespace ns3; -using CongestionPolicy = RandomCongestionPolicy<50>; +using CongestionPolicy = RandomCongestionPolicy<100>; +// using CongestionPolicy = BasicCongestionPolicy<50>; using FRRPolicy = LFAPolicy; -using SimulationQueue = FRRQueue; +using SimulationQueue = FRRQueue; +using FRRNetDevice = PointToPointFRRNetDevice; +using FRRChannel = PointToPointFRRChannel; void toggleCongestion(Ptr queue) { @@ -26,11 +30,13 @@ void toggleCongestion(Ptr queue) } NS_OBJECT_ENSURE_REGISTERED(SimulationQueue); +NS_OBJECT_ENSURE_REGISTERED(FRRChannel); +NS_OBJECT_ENSURE_REGISTERED(FRRNetDevice); template -Ptr getDevice(const NetDeviceContainer& devices) +Ptr getDevice(const NetDeviceContainer& devices) { - return devices.Get(INDEX)->GetObject(); + return devices.Get(INDEX)->GetObject(); } template @@ -41,9 +47,9 @@ Ptr getQueue(const NetDeviceContainer& devices) template void setAlternateTarget(const NetDeviceContainer& devices, - Ptr target) + Ptr target) { - getQueue(devices)->addAlternateTargets(target); + getDevice(devices)->addAlternateTarget(target); } // NS_LOG_COMPONENT_DEFINE("CongestionFastReRoute"); @@ -59,7 +65,7 @@ int main(int argc, char* argv[]) stack.Install(nodes); // Configure PointToPoint links - PointToPointHelper p2p; + PointToPointFRRHelper p2p; p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps")); p2p.SetChannelAttribute("Delay", StringValue("1ms")); @@ -68,10 +74,16 @@ int main(int argc, char* argv[]) // Install devices and channels between nodes NetDeviceContainer devices01 = p2p.Install(nodes.Get(0), nodes.Get(1)); + std::cout << "0 -> 1: " << getQueue<0>(devices01)->m_uid << std::endl; + std::cout << "1 -> 0: " << getQueue<1>(devices01)->m_uid << std::endl; NetDeviceContainer devices12 = p2p.Install(nodes.Get(1), nodes.Get(2)); + std::cout << "1 -> 2: " << getQueue<0>(devices12)->m_uid << std::endl; + std::cout << "2 -> 1: " << getQueue<1>(devices12)->m_uid << std::endl; // Add the missing link between Node 0 and Node 2 to fully connect the // network NetDeviceContainer devices02 = p2p.Install(nodes.Get(0), nodes.Get(2)); + std::cout << "0 -> 2: " << getQueue<0>(devices02)->m_uid << std::endl; + std::cout << "2 -> 0: " << getQueue<1>(devices02)->m_uid << std::endl; // Assign IP addresses Ipv4AddressHelper address; @@ -83,7 +95,9 @@ int main(int argc, char* argv[]) Ipv4InterfaceContainer interfaces02 = address.Assign(devices02); Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - + Ptr routingStream = + Create(&std::cout); + Ipv4GlobalRoutingHelper::PrintRoutingTableAllAt(Seconds(1), routingStream); /* Configure the application to generate traffic * we have node 0 sending traffic to node 2 * @@ -100,7 +114,7 @@ int main(int argc, char* argv[]) StringValue("ns3::ConstantRandomVariable[Constant=1]")); onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); - onoff.SetAttribute("DataRate", DataRateValue(DataRate("1Mbps"))); + onoff.SetAttribute("DataRate", DataRateValue(DataRate("100kbps"))); onoff.SetAttribute("PacketSize", UintegerValue(1024)); ApplicationContainer app = onoff.Install(nodes.Get(0)); @@ -125,6 +139,7 @@ int main(int argc, char* argv[]) toggleCongestion(getQueue<1>(devices12)); toggleCongestion(getQueue<1>(devices02)); + p2p.EnablePcapAll("traces/"); Simulator::Run(); Simulator::Destroy(); return 0; From 3586c291606f06c9246a51241c15864b7591c9b2 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Thu, 14 Mar 2024 02:48:49 +0000 Subject: [PATCH 27/28] :wastebasket: remove old code --- libs/frr_queue.h | 39 ++------------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/libs/frr_queue.h b/libs/frr_queue.h index 7386790e..44686027 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -5,7 +5,7 @@ #include #include -#include // For __cxa_demangle +#include #include "point_to_point_frr_net_device.h" #include "ns3/object-base.h" @@ -88,20 +88,8 @@ TypeId FRRQueue::GetTypeId() template bool FRRQueue::Enqueue(Ptr packet) { + NS_LOG_LOGIC("(" << m_uid << ") Enqueuing: " << packet); return DoEnqueue(GetContainer().end(), packet); - - NS_LOG_LOGIC("(" << m_uid << ") Checking Queue For " << packet - << ", uuid:" << packet->GetUid()); - if (m_congestionPolicy.isCongested(this)) { - NS_LOG_LOGIC("(" << m_uid - << ") Congested Route, Rerouting packet: " << packet); - // ForwardToAlternateTarget(packet); - NS_LOG_LOGIC("(" << m_uid << ") Rerouting complete"); - return false; - } - NS_LOG_LOGIC("(" << m_uid << ") Enqueue " << packet - << ", uuid:" << packet->GetUid() - << " to curr: " << GetNPackets() << " packets in queue."); } template @@ -134,27 +122,6 @@ Ptr FRRQueue::Peek() const return DoPeek(GetContainer().begin()); } -/* -template -void FRRQueue::ForwardToAlternateTarget( - Ptr packet) -{ - Ptr alternativeTarget = - m_frrPolicy.selectAlternativeTarget(); - if (alternativeTarget) { - PppHeader header; - packet->RemoveHeader(header, 2); - Ipv4Header ipHeader; - packet->PeekHeader(ipHeader); - NS_LOG_LOGIC("(" << m_uid << ") Forwarding packet to: " << -ipHeader.GetDestination()); bool rc = alternativeTarget->Send(packet, -ipHeader.GetDestination(), 0x0800); NS_LOG_LOGIC("(" << m_uid << ") Forwarded -packet with: " << rc); } else { NS_LOG_LOGIC("(" << m_uid - << ") No alternative target found, dropping packet."); - } -} -*/ - template std::string FRRQueue::makeQueueString() { @@ -177,8 +144,6 @@ const std::string& FRRQueue::getQueueString() return result; } -// NS_LOG_COMPONENT_DEFINE("FRRQueue"); - } // namespace ns3 #endif From 7de17dbe0f6321400c649d46e2cb8f43add09541 Mon Sep 17 00:00:00 2001 From: charliebarber Date: Thu, 14 Mar 2024 15:02:53 +0000 Subject: [PATCH 28/28] Replaced reserved DISCARD port 9 with 50000 --- src/lfa_random.cc | 2 +- traces/placeholder | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 traces/placeholder diff --git a/src/lfa_random.cc b/src/lfa_random.cc index 519bb9af..dde5c441 100644 --- a/src/lfa_random.cc +++ b/src/lfa_random.cc @@ -107,7 +107,7 @@ int main(int argc, char* argv[]) * / \ * 0 -----> 2 */ - uint16_t port = 9; + uint16_t port = 50000; OnOffHelper onoff("ns3::UdpSocketFactory", InetSocketAddress(interfaces12.GetAddress(1), port)); onoff.SetAttribute("OnTime", diff --git a/traces/placeholder b/traces/placeholder deleted file mode 100644 index 8b137891..00000000 --- a/traces/placeholder +++ /dev/null @@ -1 +0,0 @@ -