Update README and add contrib dir
This commit is contained in:
28
contrib/ethernet/CMakeLists.txt
Normal file
28
contrib/ethernet/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
check_include_file_cxx(stdint.h HAVE_STDINT_H)
|
||||
if(HAVE_STDINT_H)
|
||||
add_definitions(-DHAVE_STDINT_H)
|
||||
endif()
|
||||
|
||||
set(examples_as_tests_sources)
|
||||
if(${ENABLE_EXAMPLES})
|
||||
set(examples_as_tests_sources
|
||||
#test/ethernet-examples-test-suite.cc
|
||||
)
|
||||
endif()
|
||||
|
||||
build_lib(
|
||||
LIBNAME ethernet
|
||||
SOURCE_FILES model/ethernet-channel.cc
|
||||
model/ethernet-header2.cc
|
||||
model/ethernet-net-device.cc
|
||||
model/switch-net-device.cc
|
||||
model/switch-channel.cc
|
||||
HEADER_FILES model/ethernet-channel.h
|
||||
model/ethernet-header2.h
|
||||
model/ethernet-net-device.h
|
||||
model/switch-net-device.h
|
||||
model/switch-channel.h
|
||||
LIBRARIES_TO_LINK ${libcore}
|
||||
TEST_SOURCES test/ethernet-test-suite.cc
|
||||
${examples_as_tests_sources}
|
||||
)
|
||||
22
contrib/ethernet/examples/CMakeLists.txt
Normal file
22
contrib/ethernet/examples/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
set(base_examples
|
||||
ethernet-point2point
|
||||
ethernet-point2point-withPropagationDelay
|
||||
ethernet-point2point-withSmallFifo
|
||||
ethernet-switched
|
||||
ethernet-switched-withLatencyCallback
|
||||
ethernet-switched-withPcap
|
||||
ethernet-switched-withRxTxCallback
|
||||
)
|
||||
foreach(
|
||||
example
|
||||
${base_examples}
|
||||
)
|
||||
build_lib_example(
|
||||
NAME ${example}
|
||||
SOURCE_FILES ${example}.cc
|
||||
LIBRARIES_TO_LINK ${libcore}
|
||||
${libnetwork}
|
||||
${libethernet}
|
||||
${libtraffic-generator}
|
||||
)
|
||||
endforeach()
|
||||
94
contrib/ethernet/examples/ethernet-point2point-10Gb.cc
Normal file
94
contrib/ethernet/examples/ethernet-point2point-10Gb.cc
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
|
||||
#include "ns3/ethernet-net-device.h"
|
||||
#include "ns3/ethernet-channel.h"
|
||||
#include "ns3/ethernet-generator.h"
|
||||
#include "ns3/ethernet-header2.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Example of the use of ethernet-net-device.cc ethernet-channel.cc on a network
|
||||
* composed of two end-stations connected by a 10Gb/s full duplex link
|
||||
* ES1 ====== ES2
|
||||
*/
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("Example");
|
||||
|
||||
//A callback to log the pkt reception
|
||||
static void
|
||||
MacRxCallback(std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
NS_LOG_INFO((Simulator::Now()).As(Time::FS) << " \t" << context << " : Pkt #" << p->GetUid() << " received !");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
//Enable logging
|
||||
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("EthernetGenerator", LOG_LEVEL_INFO);
|
||||
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
//Mandatory for multi-giga
|
||||
Time::SetResolution(Time::PS);
|
||||
|
||||
//Create two nodes
|
||||
Ptr<Node> n0 = CreateObject<Node>();
|
||||
Names::Add("ES1", n0);
|
||||
Ptr<Node> n1 = CreateObject<Node>();
|
||||
Names::Add("ES2", n1);
|
||||
|
||||
//Create and add a netDevice to each node
|
||||
Ptr<EthernetNetDevice> net0 = CreateObject<EthernetNetDevice>();
|
||||
net0->SetAttribute("DataRate", DataRateValue(DataRate("10Gb/s")));
|
||||
n0->AddDevice(net0);
|
||||
Names::Add("ES1#01", net0);
|
||||
Ptr<EthernetNetDevice> net1 = CreateObject<EthernetNetDevice>();
|
||||
net1->SetAttribute("DataRate", DataRateValue(DataRate("10Gb/s")));
|
||||
n1->AddDevice(net1);
|
||||
Names::Add("ES2#01", net1);
|
||||
|
||||
//Create a Ethernet Channel and attach it two the two netDevices
|
||||
Ptr<EthernetChannel> channel = CreateObject<EthernetChannel>();
|
||||
net0->Attach(channel);
|
||||
net1->Attach(channel);
|
||||
|
||||
//Allocate a Mac address and create a FIFO (for the output port)
|
||||
//for each netDevice.
|
||||
net0->SetAddress(Mac48Address::Allocate());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
net1->SetAddress(Mac48Address::Allocate());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
//Application description
|
||||
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||||
app0->Setup(net0);
|
||||
app0->SetAttribute("BurstSize", UintegerValue(2));
|
||||
app0->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app0->SetAttribute("Period", TimeValue(Seconds(5)));
|
||||
|
||||
n0->AddApplication(app0);
|
||||
app0->SetStartTime(Seconds(0));
|
||||
app0->SetStopTime(Seconds(10));
|
||||
|
||||
//Callback to display the packet received log
|
||||
std::string context = Names::FindName(n1) + ":" + Names::FindName(net1);
|
||||
net1->TraceConnectWithoutContext("MacRx", MakeBoundCallback(&MacRxCallback, context));
|
||||
|
||||
//Execute the simulation
|
||||
Simulator::Stop(Seconds(10));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
|
||||
#include "ns3/ethernet-net-device.h"
|
||||
#include "ns3/ethernet-channel.h"
|
||||
#include "ns3/ethernet-generator.h"
|
||||
#include "ns3/ethernet-header2.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Example of the use of ethernet-net-device.cc ethernet-channel.cc on a network
|
||||
* composed of two end-stations connected by a 100Mb/s full duplex link
|
||||
* ES1 ====== ES2
|
||||
*/
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("Example");
|
||||
|
||||
//A callback to log the pkt reception
|
||||
static void
|
||||
MacRxCallback(std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << context << " : Pkt #" << p->GetUid() << " received !");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
//Enable logging
|
||||
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("EthernetGenerator", LOG_LEVEL_INFO);
|
||||
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
//Create two nodes
|
||||
Ptr<Node> n0 = CreateObject<Node>();
|
||||
Names::Add("ES1", n0);
|
||||
Ptr<Node> n1 = CreateObject<Node>();
|
||||
Names::Add("ES2", n1);
|
||||
|
||||
//Create and add a netDevice to each node
|
||||
Ptr<EthernetNetDevice> net0 = CreateObject<EthernetNetDevice>();
|
||||
net0->SetAttribute("DataRate", DataRateValue(DataRate("100Mb/s")));
|
||||
n0->AddDevice(net0);
|
||||
Names::Add("ES1#01", net0);
|
||||
Ptr<EthernetNetDevice> net1 = CreateObject<EthernetNetDevice>();
|
||||
net1->SetAttribute("DataRate", DataRateValue(DataRate("100Mb/s")));
|
||||
n1->AddDevice(net1);
|
||||
Names::Add("ES2#01", net1);
|
||||
|
||||
//Create a Ethernet Channel with a 10µs propagation delay (~2km) and attach
|
||||
//it two the two netDevices
|
||||
Ptr<EthernetChannel> channel = CreateObject<EthernetChannel>();
|
||||
channel->SetAttribute("Delay", TimeValue(MicroSeconds(10)));
|
||||
net0->Attach(channel);
|
||||
net1->Attach(channel);
|
||||
|
||||
//Allocate a Mac address and create a FIFO (for the output port)
|
||||
//for each netDevice.
|
||||
net0->SetAddress(Mac48Address::Allocate());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
net1->SetAddress(Mac48Address::Allocate());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
//Application description
|
||||
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||||
app0->Setup(net0);
|
||||
app0->SetAttribute("BurstSize", UintegerValue(2));
|
||||
app0->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app0->SetAttribute("Period", TimeValue(Seconds(5)));
|
||||
|
||||
n0->AddApplication(app0);
|
||||
app0->SetStartTime(Seconds(0));
|
||||
app0->SetStopTime(Seconds(10));
|
||||
|
||||
//Callback to display the packet received log
|
||||
std::string context = Names::FindName(n1) + ":" + Names::FindName(net1);
|
||||
net1->TraceConnectWithoutContext("MacRx", MakeBoundCallback(&MacRxCallback, context));
|
||||
|
||||
//Execute the simulation
|
||||
Simulator::Stop(Seconds(10));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
108
contrib/ethernet/examples/ethernet-point2point-withSmallFifo.cc
Normal file
108
contrib/ethernet/examples/ethernet-point2point-withSmallFifo.cc
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
|
||||
#include "ns3/ethernet-net-device.h"
|
||||
#include "ns3/ethernet-channel.h"
|
||||
#include "ns3/ethernet-generator.h"
|
||||
#include "ns3/ethernet-header2.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Example of the use of ethernet-net-device.cc ethernet-channel.cc on a network
|
||||
* composed of two end-stations connected by a 100Mb/s full duplex link
|
||||
* ES1 ====== ES2
|
||||
*/
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("Example");
|
||||
|
||||
//A callback to log the pkt reception
|
||||
static void
|
||||
MacRxCallback(std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << context << " : Pkt #" << p->GetUid() << " received !");
|
||||
}
|
||||
|
||||
//A callback to log the pkt drop due to FIFO offerflow
|
||||
static void
|
||||
MacTxDropCallback(std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << context << " : Pkt #" << p->GetUid() << " drop due to FIFO overflow !");
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
//Enable logging
|
||||
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("EthernetGenerator", LOG_LEVEL_INFO);
|
||||
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
//Create two nodes
|
||||
Ptr<Node> n0 = CreateObject<Node>();
|
||||
Names::Add("ES1", n0);
|
||||
Ptr<Node> n1 = CreateObject<Node>();
|
||||
Names::Add("ES2", n1);
|
||||
|
||||
//Create and add a netDevice to each node
|
||||
Ptr<EthernetNetDevice> net0 = CreateObject<EthernetNetDevice>();
|
||||
net0->SetAttribute("DataRate", DataRateValue(DataRate("100Mb/s")));
|
||||
n0->AddDevice(net0);
|
||||
Names::Add("ES1#01", net0);
|
||||
Ptr<EthernetNetDevice> net1 = CreateObject<EthernetNetDevice>();
|
||||
net1->SetAttribute("DataRate", DataRateValue(DataRate("100Mb/s")));
|
||||
n1->AddDevice(net1);
|
||||
Names::Add("ES2#01", net1);
|
||||
|
||||
//Create a Ethernet Channel and attach it two the two netDevices
|
||||
Ptr<EthernetChannel> channel = CreateObject<EthernetChannel>();
|
||||
net0->Attach(channel);
|
||||
net1->Attach(channel);
|
||||
|
||||
//Allocate a Mac address for each netDevice.
|
||||
net0->SetAddress(Mac48Address::Allocate());
|
||||
net1->SetAddress(Mac48Address::Allocate());
|
||||
|
||||
//Allocate a FIFO for each netDevice.
|
||||
//5 packets size FIFO for net0
|
||||
Ptr<DropTailQueue<Packet>> q = CreateObject<DropTailQueue<Packet>>();
|
||||
q->SetAttribute("MaxSize", QueueSizeValue(QueueSize("5p")));
|
||||
net0->SetQueue(q);
|
||||
//Default size FIFO (i.e. 100 packets) for net1
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
//Application description
|
||||
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||||
app0->Setup(net0);
|
||||
app0->SetAttribute("BurstSize", UintegerValue(10));
|
||||
app0->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app0->SetAttribute("Period", TimeValue(Seconds(5)));
|
||||
|
||||
n0->AddApplication(app0);
|
||||
app0->SetStartTime(Seconds(0));
|
||||
app0->SetStopTime(Seconds(10));
|
||||
|
||||
//Callback to display the packet received log
|
||||
std::string context = Names::FindName(n1) + ":" + Names::FindName(net1);
|
||||
net1->TraceConnectWithoutContext("MacRx", MakeBoundCallback(&MacRxCallback, context));
|
||||
|
||||
//Callback to display the packet drop log
|
||||
context = Names::FindName(n0) + ":" + Names::FindName(net0);
|
||||
net0->TraceConnectWithoutContext("MacTxDrop", MakeBoundCallback(&MacTxDropCallback, context));
|
||||
|
||||
//Execute the simulation
|
||||
Simulator::Stop(Seconds(10));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
91
contrib/ethernet/examples/ethernet-point2point.cc
Normal file
91
contrib/ethernet/examples/ethernet-point2point.cc
Normal file
@@ -0,0 +1,91 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
|
||||
#include "ns3/ethernet-net-device.h"
|
||||
#include "ns3/ethernet-channel.h"
|
||||
#include "ns3/ethernet-generator.h"
|
||||
#include "ns3/ethernet-header2.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Example of the use of ethernet-net-device.cc ethernet-channel.cc on a network
|
||||
* composed of two end-stations connected by a 100Mb/s full duplex link
|
||||
* ES1 ====== ES2
|
||||
*/
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("Example");
|
||||
|
||||
//A callback to log the pkt reception
|
||||
static void
|
||||
MacRxCallback(std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << context << " : Pkt #" << p->GetUid() << " received !");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
//Enable logging
|
||||
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("EthernetGenerator", LOG_LEVEL_INFO);
|
||||
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
//Create two nodes
|
||||
Ptr<Node> n0 = CreateObject<Node>();
|
||||
Names::Add("ES1", n0);
|
||||
Ptr<Node> n1 = CreateObject<Node>();
|
||||
Names::Add("ES2", n1);
|
||||
|
||||
//Create and add a netDevice to each node
|
||||
Ptr<EthernetNetDevice> net0 = CreateObject<EthernetNetDevice>();
|
||||
net0->SetAttribute("DataRate", DataRateValue(DataRate("100Mb/s")));
|
||||
n0->AddDevice(net0);
|
||||
Names::Add("ES1#01", net0);
|
||||
Ptr<EthernetNetDevice> net1 = CreateObject<EthernetNetDevice>();
|
||||
net1->SetAttribute("DataRate", DataRateValue(DataRate("100Mb/s")));
|
||||
n1->AddDevice(net1);
|
||||
Names::Add("ES2#01", net1);
|
||||
|
||||
//Create a Ethernet Channel and attach it two the two netDevices
|
||||
Ptr<EthernetChannel> channel = CreateObject<EthernetChannel>();
|
||||
net0->Attach(channel);
|
||||
net1->Attach(channel);
|
||||
|
||||
//Allocate a Mac address and create a FIFO (for the output port)
|
||||
//for each netDevice.
|
||||
net0->SetAddress(Mac48Address::Allocate());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
net1->SetAddress(Mac48Address::Allocate());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
//Application description
|
||||
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||||
app0->Setup(net0);
|
||||
app0->SetAttribute("BurstSize", UintegerValue(2));
|
||||
app0->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app0->SetAttribute("Period", TimeValue(Seconds(5)));
|
||||
|
||||
n0->AddApplication(app0);
|
||||
app0->SetStartTime(Seconds(0));
|
||||
app0->SetStopTime(Seconds(10));
|
||||
|
||||
//Callback to display the packet received log
|
||||
std::string context = Names::FindName(n1) + ":" + Names::FindName(net1);
|
||||
net1->TraceConnectWithoutContext("MacRx", MakeBoundCallback(&MacRxCallback, context));
|
||||
|
||||
//Execute the simulation
|
||||
Simulator::Stop(Seconds(10));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
#include "ns3/timestamp-tag.h"
|
||||
#include "ns3/trace-helper.h"
|
||||
#include <fstream>
|
||||
|
||||
#include "ns3/ethernet-net-device.h"
|
||||
#include "ns3/ethernet-channel.h"
|
||||
#include "ns3/ethernet-generator.h"
|
||||
#include "ns3/ethernet-header2.h"
|
||||
#include "ns3/switch-net-device.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Example of the use of switch-net-device.cc switch-channel.cc
|
||||
* ethernet-net-device.cc ethernet-channel.cc on a network composed of three
|
||||
* end-stations connected with a 1Gb/s full duplex link
|
||||
* ES1 ==== SW ==== ES2
|
||||
* ==== ES3
|
||||
*/
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("Example");
|
||||
|
||||
|
||||
//A callback to log the pkt latency
|
||||
static void
|
||||
LatencyCallback(std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
TimestampTag tag;
|
||||
if (!p->FindFirstMatchingByteTag(tag))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Time arrival = Simulator::Now();
|
||||
Time latency = arrival - tag.GetTimestamp();
|
||||
|
||||
Ptr<Packet> originalPacket = p->Copy();
|
||||
EthernetHeader2 ethHeader;
|
||||
originalPacket->RemoveHeader(ethHeader);
|
||||
NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << context << " : Pkt #" << p->GetUid() << " received from " << ethHeader.GetSrc() << "(VID:" << ethHeader.GetVid() << ") with a latency=" << latency.GetNanoSeconds() <<"ns");
|
||||
}
|
||||
|
||||
//A callback to write in a file the pkt latency hop by hop
|
||||
static void
|
||||
LatencyHopByHopCallback(Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
Ptr<Packet> originalPacket = p->Copy();
|
||||
EthernetHeader2 ethHeader;
|
||||
originalPacket->RemoveHeader(ethHeader);
|
||||
|
||||
*stream->GetStream() << context << " : Packet #"<< p->GetUid() << " from "<< ethHeader.GetSrc() << "(VID:" << ethHeader.GetVid() << ") : ";
|
||||
TimestampTag tag;
|
||||
TypeId tid = tag.GetInstanceTypeId();
|
||||
ByteTagIterator i = p->GetByteTagIterator();
|
||||
while (i.HasNext())
|
||||
{
|
||||
ByteTagIterator::Item item = i.Next();
|
||||
if (tid == item.GetTypeId())
|
||||
{
|
||||
item.GetTag(tag);
|
||||
*stream->GetStream() << tag.GetTimestamp().GetNanoSeconds() << ",";
|
||||
}
|
||||
}
|
||||
*stream->GetStream() << "\n";
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
//Enable logging
|
||||
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("EthernetGenerator", LOG_LEVEL_INFO);
|
||||
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
//Create four nodes
|
||||
Ptr<Node> n0 = CreateObject<Node>();
|
||||
Names::Add("ES1", n0);
|
||||
Ptr<Node> n1 = CreateObject<Node>();
|
||||
Names::Add("ES2", n1);
|
||||
Ptr<Node> n2 = CreateObject<Node>();
|
||||
Names::Add("ES3", n2);
|
||||
Ptr<Node> n3 = CreateObject<Node>();
|
||||
Names::Add("SW", n3);
|
||||
|
||||
//Create and add a netDevice to each end station node
|
||||
Ptr<EthernetNetDevice> net0 = CreateObject<EthernetNetDevice>();
|
||||
n0->AddDevice(net0);
|
||||
Names::Add("ES1#01", net0);
|
||||
Ptr<EthernetNetDevice> net1 = CreateObject<EthernetNetDevice>();
|
||||
n1->AddDevice(net1);
|
||||
Names::Add("ES2#01", net1);
|
||||
Ptr<EthernetNetDevice> net2 = CreateObject<EthernetNetDevice>();
|
||||
n2->AddDevice(net2);
|
||||
Names::Add("ES3#01", net2);
|
||||
|
||||
//Create and add a netDevice to each switch port
|
||||
Ptr<EthernetNetDevice> swnet0 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet0);
|
||||
Names::Add("SW#01", swnet0);
|
||||
Ptr<EthernetNetDevice> swnet1 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet1);
|
||||
Names::Add("SW#02", swnet1);
|
||||
Ptr<EthernetNetDevice> swnet2 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet2);
|
||||
Names::Add("SW#03", swnet2);
|
||||
|
||||
//Create Ethernet Channels and connect switch to the end-stations
|
||||
Ptr<EthernetChannel> channel0 = CreateObject<EthernetChannel>();
|
||||
net0->Attach(channel0);
|
||||
swnet0->Attach(channel0);
|
||||
Ptr<EthernetChannel> channel1 = CreateObject<EthernetChannel>();
|
||||
net1->Attach(channel1);
|
||||
swnet1->Attach(channel1);
|
||||
Ptr<EthernetChannel> channel2 = CreateObject<EthernetChannel>();
|
||||
net2->Attach(channel2);
|
||||
swnet2->Attach(channel2);
|
||||
|
||||
//Create and add a switch net device to the switch node
|
||||
Ptr<SwitchNetDevice> sw = CreateObject<SwitchNetDevice>();
|
||||
sw->SetAttribute("MinForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
sw->SetAttribute("MaxForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
n3->AddDevice(sw);
|
||||
sw->AddSwitchPort(swnet0);
|
||||
sw->AddSwitchPort(swnet1);
|
||||
sw->AddSwitchPort(swnet2);
|
||||
|
||||
//Allocate a Mac address and create 2 FIFOs (for the output port)
|
||||
//for each netDevice.
|
||||
net0->SetAddress(Mac48Address::Allocate());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net1->SetAddress(Mac48Address::Allocate());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net2->SetAddress(Mac48Address::Allocate());
|
||||
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
sw->SetAddress(Mac48Address::Allocate());
|
||||
swnet0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
//Add forwarding table
|
||||
sw->AddForwardingTableEntry(Mac48Address::ConvertFrom(net2->GetAddress()), 1, {swnet2});
|
||||
|
||||
//Application description
|
||||
//ES1 -> ES3 with priority 1
|
||||
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||||
app0->Setup(net0);
|
||||
app0->SetAttribute("Address", AddressValue(net2->GetAddress()));
|
||||
app0->SetAttribute("BurstSize", UintegerValue(2));
|
||||
app0->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app0->SetAttribute("Period", TimeValue(Seconds(5)));
|
||||
app0->SetAttribute("VlanID", UintegerValue(1));
|
||||
app0->SetAttribute("PCP", UintegerValue(1));
|
||||
n0->AddApplication(app0);
|
||||
app0->SetStartTime(Seconds(0));
|
||||
app0->SetStopTime(Seconds(10));
|
||||
|
||||
//Callback to display the packet latency log
|
||||
std::string context = Names::FindName(n2) + ":" + Names::FindName(net2);
|
||||
net2->TraceConnectWithoutContext("Latency", MakeBoundCallback(&LatencyCallback, context));
|
||||
|
||||
//Callback to write the packet latency hop by hop in a file
|
||||
AsciiTraceHelper asciiTraceHelper;
|
||||
std::string filename = "example.hopByHopLat";
|
||||
Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream(filename);
|
||||
net2->TraceConnectWithoutContext("Latency", MakeBoundCallback(&LatencyHopByHopCallback, stream, context));
|
||||
|
||||
//Execute the simulation
|
||||
Simulator::Stop(Seconds(10));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
176
contrib/ethernet/examples/ethernet-switched-withPcap.cc
Normal file
176
contrib/ethernet/examples/ethernet-switched-withPcap.cc
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
#include "ns3/trace-helper.h"
|
||||
#include <fstream>
|
||||
|
||||
#include "ns3/ethernet-net-device.h"
|
||||
#include "ns3/ethernet-channel.h"
|
||||
#include "ns3/ethernet-generator.h"
|
||||
#include "ns3/ethernet-header2.h"
|
||||
#include "ns3/switch-net-device.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Example of the use of switch-net-device.cc switch-channel.cc
|
||||
* ethernet-net-device.cc ethernet-channel.cc on a network composed of three
|
||||
* end-stations connected with a 1Gb/s full duplex link
|
||||
* ES1 ==== SW ==== ES2
|
||||
* ==== ES3
|
||||
*/
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("Example");
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
//Enable logging
|
||||
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||||
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
//Create four nodes
|
||||
Ptr<Node> n0 = CreateObject<Node>();
|
||||
Names::Add("ES1", n0);
|
||||
Ptr<Node> n1 = CreateObject<Node>();
|
||||
Names::Add("ES2", n1);
|
||||
Ptr<Node> n2 = CreateObject<Node>();
|
||||
Names::Add("ES3", n2);
|
||||
Ptr<Node> n3 = CreateObject<Node>();
|
||||
Names::Add("SW", n3);
|
||||
|
||||
//Create and add a netDevice to each end station node
|
||||
Ptr<EthernetNetDevice> net0 = CreateObject<EthernetNetDevice>();
|
||||
n0->AddDevice(net0);
|
||||
Names::Add("ES1#01", net0);
|
||||
Ptr<EthernetNetDevice> net1 = CreateObject<EthernetNetDevice>();
|
||||
n1->AddDevice(net1);
|
||||
Names::Add("ES2#01", net1);
|
||||
Ptr<EthernetNetDevice> net2 = CreateObject<EthernetNetDevice>();
|
||||
n2->AddDevice(net2);
|
||||
Names::Add("ES3#01", net2);
|
||||
|
||||
//Create and add a netDevice to each switch port
|
||||
Ptr<EthernetNetDevice> swnet0 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet0);
|
||||
Names::Add("SW#01", swnet0);
|
||||
Ptr<EthernetNetDevice> swnet1 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet1);
|
||||
Names::Add("SW#02", swnet1);
|
||||
Ptr<EthernetNetDevice> swnet2 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet2);
|
||||
Names::Add("SW#03", swnet2);
|
||||
|
||||
//Create Ethernet Channels and connect switch to the end-stations
|
||||
Ptr<EthernetChannel> channel0 = CreateObject<EthernetChannel>();
|
||||
net0->Attach(channel0);
|
||||
swnet0->Attach(channel0);
|
||||
Ptr<EthernetChannel> channel1 = CreateObject<EthernetChannel>();
|
||||
net1->Attach(channel1);
|
||||
swnet1->Attach(channel1);
|
||||
Ptr<EthernetChannel> channel2 = CreateObject<EthernetChannel>();
|
||||
net2->Attach(channel2);
|
||||
swnet2->Attach(channel2);
|
||||
|
||||
//Create and add a switch net device to the switch node
|
||||
Ptr<SwitchNetDevice> sw = CreateObject<SwitchNetDevice>();
|
||||
sw->SetAttribute("MinForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
sw->SetAttribute("MaxForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
n3->AddDevice(sw);
|
||||
sw->AddSwitchPort(swnet0);
|
||||
sw->AddSwitchPort(swnet1);
|
||||
sw->AddSwitchPort(swnet2);
|
||||
|
||||
//Allocate a Mac address and create 2 FIFOs (for the output port)
|
||||
//for each netDevice.
|
||||
net0->SetAddress(Mac48Address::Allocate());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net1->SetAddress(Mac48Address::Allocate());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net2->SetAddress(Mac48Address::Allocate());
|
||||
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
sw->SetAddress(Mac48Address::Allocate());
|
||||
swnet0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
//Add forwarding table
|
||||
sw->AddForwardingTableEntry(Mac48Address::ConvertFrom(net2->GetAddress()), 1, {swnet2});
|
||||
|
||||
//Application description
|
||||
//ES1 -> ES3 with priority 1
|
||||
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||||
app0->Setup(net0);
|
||||
app0->SetAttribute("Address", AddressValue(net2->GetAddress()));
|
||||
app0->SetAttribute("BurstSize", UintegerValue(2));
|
||||
app0->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app0->SetAttribute("Period", TimeValue(Seconds(5)));
|
||||
app0->SetAttribute("VlanID", UintegerValue(1));
|
||||
app0->SetAttribute("PCP", UintegerValue(1));
|
||||
n0->AddApplication(app0);
|
||||
app0->SetStartTime(Seconds(0));
|
||||
app0->SetStopTime(Seconds(10));
|
||||
|
||||
//ES2 -> ES1 and ES3 with priority 0
|
||||
Ptr<EthernetGenerator> app1 = CreateObject<EthernetGenerator>();
|
||||
app1->Setup(net1);
|
||||
app1->SetAttribute("Address", AddressValue(Mac48Address("ff:ff:ff:ff:ff:ff")));
|
||||
app1->SetAttribute("BurstSize", UintegerValue(1));
|
||||
app1->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app1->SetAttribute("Period", TimeValue(Seconds(2.5)));
|
||||
app1->SetAttribute("VlanID", UintegerValue(2));
|
||||
app1->SetAttribute("PCP", UintegerValue(0));
|
||||
n1->AddApplication(app1);
|
||||
app1->SetStartTime(Seconds(0));
|
||||
app1->SetStopTime(Seconds(5));
|
||||
|
||||
|
||||
//Enable pcap generation
|
||||
PcapHelper pcapHelper;
|
||||
std::string pcapFilename;
|
||||
std::string prefix = "example";
|
||||
Ptr<PcapFileWrapper> file;
|
||||
pcapFilename = pcapHelper.GetFilenameFromDevice(prefix, net0);
|
||||
file = pcapHelper.CreateFile(pcapFilename, std::ios::out, PcapHelper::DLT_EN10MB);
|
||||
pcapHelper.HookDefaultSink<EthernetNetDevice>(net0, "Sniffer", file);
|
||||
|
||||
pcapFilename = pcapHelper.GetFilenameFromDevice(prefix, net1);
|
||||
file = pcapHelper.CreateFile(pcapFilename, std::ios::out, PcapHelper::DLT_EN10MB);
|
||||
pcapHelper.HookDefaultSink<EthernetNetDevice>(net1, "Sniffer", file);
|
||||
|
||||
pcapFilename = pcapHelper.GetFilenameFromDevice(prefix, net2);
|
||||
file = pcapHelper.CreateFile(pcapFilename, std::ios::out, PcapHelper::DLT_EN10MB);
|
||||
pcapHelper.HookDefaultSink<EthernetNetDevice>(net2, "Sniffer", file);
|
||||
|
||||
pcapFilename = pcapHelper.GetFilenameFromDevice(prefix, swnet0);
|
||||
file = pcapHelper.CreateFile(pcapFilename, std::ios::out, PcapHelper::DLT_EN10MB);
|
||||
pcapHelper.HookDefaultSink<EthernetNetDevice>(swnet0, "Sniffer", file);
|
||||
|
||||
pcapFilename = pcapHelper.GetFilenameFromDevice(prefix, swnet1);
|
||||
file = pcapHelper.CreateFile(pcapFilename, std::ios::out, PcapHelper::DLT_EN10MB);
|
||||
pcapHelper.HookDefaultSink<EthernetNetDevice>(swnet1, "Sniffer", file);
|
||||
|
||||
pcapFilename = pcapHelper.GetFilenameFromDevice(prefix, swnet2);
|
||||
file = pcapHelper.CreateFile(pcapFilename, std::ios::out, PcapHelper::DLT_EN10MB);
|
||||
pcapHelper.HookDefaultSink<EthernetNetDevice>(swnet2, "Sniffer", file);
|
||||
|
||||
|
||||
//Execute the simulation
|
||||
Simulator::Stop(Seconds(10));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
172
contrib/ethernet/examples/ethernet-switched-withRxTxCallback.cc
Normal file
172
contrib/ethernet/examples/ethernet-switched-withRxTxCallback.cc
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
#include "ns3/trace-helper.h"
|
||||
#include <fstream>
|
||||
|
||||
#include "ns3/ethernet-net-device.h"
|
||||
#include "ns3/ethernet-channel.h"
|
||||
#include "ns3/ethernet-generator.h"
|
||||
#include "ns3/ethernet-header2.h"
|
||||
#include "ns3/switch-net-device.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Example of the use of switch-net-device.cc switch-channel.cc
|
||||
* ethernet-net-device.cc ethernet-channel.cc on a network composed of three
|
||||
* end-stations connected with a 1Gb/s full duplex link
|
||||
* ES1 ==== SW ==== ES2
|
||||
* ==== ES3
|
||||
*/
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("Example");
|
||||
|
||||
static void
|
||||
MacTxCallback(Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
Time t = Simulator::Now();
|
||||
Ptr<Packet> originalPacket = p->Copy();
|
||||
EthernetHeader2 ethHeader;
|
||||
originalPacket->RemoveHeader(ethHeader);
|
||||
|
||||
*stream->GetStream() << "NetDevice:" << context << " : At "<< t.GetNanoSeconds() << " FIFO Entry => Packet #"<< p->GetUid() << " from "<< ethHeader.GetSrc() << "(VID:" << ethHeader.GetVid() << ")\n";
|
||||
}
|
||||
|
||||
static void
|
||||
PhyTxBeginCallback(Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
Time t = Simulator::Now();
|
||||
Ptr<Packet> originalPacket = p->Copy();
|
||||
EthernetHeader2 ethHeader;
|
||||
originalPacket->RemoveHeader(ethHeader);
|
||||
*stream->GetStream() << "NetDevice:" << context << " : At "<< t.GetNanoSeconds() << " FIFO Exit => Packet #"<< p->GetUid() << " from "<< ethHeader.GetSrc() << "(VID:" << ethHeader.GetVid() << ")\n";
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
//Enable logging
|
||||
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||||
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
//Create four nodes
|
||||
Ptr<Node> n0 = CreateObject<Node>();
|
||||
Names::Add("ES1", n0);
|
||||
Ptr<Node> n1 = CreateObject<Node>();
|
||||
Names::Add("ES2", n1);
|
||||
Ptr<Node> n2 = CreateObject<Node>();
|
||||
Names::Add("ES3", n2);
|
||||
Ptr<Node> n3 = CreateObject<Node>();
|
||||
Names::Add("SW", n3);
|
||||
|
||||
//Create and add a netDevice to each end station node
|
||||
Ptr<EthernetNetDevice> net0 = CreateObject<EthernetNetDevice>();
|
||||
n0->AddDevice(net0);
|
||||
Names::Add("ES1#01", net0);
|
||||
Ptr<EthernetNetDevice> net1 = CreateObject<EthernetNetDevice>();
|
||||
n1->AddDevice(net1);
|
||||
Names::Add("ES2#01", net1);
|
||||
Ptr<EthernetNetDevice> net2 = CreateObject<EthernetNetDevice>();
|
||||
n2->AddDevice(net2);
|
||||
Names::Add("ES3#01", net2);
|
||||
|
||||
//Create and add a netDevice to each switch port
|
||||
Ptr<EthernetNetDevice> swnet0 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet0);
|
||||
Names::Add("SW#01", swnet0);
|
||||
Ptr<EthernetNetDevice> swnet1 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet1);
|
||||
Names::Add("SW#02", swnet1);
|
||||
Ptr<EthernetNetDevice> swnet2 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet2);
|
||||
Names::Add("SW#03", swnet2);
|
||||
|
||||
//Create Ethernet Channels and connect switch to the end-stations
|
||||
Ptr<EthernetChannel> channel0 = CreateObject<EthernetChannel>();
|
||||
net0->Attach(channel0);
|
||||
swnet0->Attach(channel0);
|
||||
Ptr<EthernetChannel> channel1 = CreateObject<EthernetChannel>();
|
||||
net1->Attach(channel1);
|
||||
swnet1->Attach(channel1);
|
||||
Ptr<EthernetChannel> channel2 = CreateObject<EthernetChannel>();
|
||||
net2->Attach(channel2);
|
||||
swnet2->Attach(channel2);
|
||||
|
||||
//Create and add a switch net device to the switch node
|
||||
Ptr<SwitchNetDevice> sw = CreateObject<SwitchNetDevice>();
|
||||
sw->SetAttribute("MinForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
sw->SetAttribute("MaxForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
n3->AddDevice(sw);
|
||||
sw->AddSwitchPort(swnet0);
|
||||
sw->AddSwitchPort(swnet1);
|
||||
sw->AddSwitchPort(swnet2);
|
||||
|
||||
//Allocate a Mac address and create 2 FIFOs (for the output port)
|
||||
//for each netDevice.
|
||||
net0->SetAddress(Mac48Address::Allocate());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net1->SetAddress(Mac48Address::Allocate());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net2->SetAddress(Mac48Address::Allocate());
|
||||
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
sw->SetAddress(Mac48Address::Allocate());
|
||||
swnet0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
//Add forwarding table
|
||||
sw->AddForwardingTableEntry(Mac48Address::ConvertFrom(net2->GetAddress()), 1, {swnet2});
|
||||
|
||||
//Application description
|
||||
//ES1 -> ES3 with priority 1
|
||||
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||||
app0->Setup(net0);
|
||||
app0->SetAttribute("Address", AddressValue(net2->GetAddress()));
|
||||
app0->SetAttribute("BurstSize", UintegerValue(2));
|
||||
app0->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app0->SetAttribute("Period", TimeValue(Seconds(5)));
|
||||
app0->SetAttribute("VlanID", UintegerValue(1));
|
||||
app0->SetAttribute("PCP", UintegerValue(1));
|
||||
n0->AddApplication(app0);
|
||||
app0->SetStartTime(Seconds(0));
|
||||
app0->SetStopTime(Seconds(10));
|
||||
|
||||
|
||||
//Callback to wirte FIFO entry and exit event in a file
|
||||
AsciiTraceHelper asciiTraceHelper;
|
||||
std::string filename = "example.fifo";
|
||||
Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream(filename);
|
||||
net0->TraceConnectWithoutContext("MacTx", MakeBoundCallback(&MacTxCallback, stream, Names::FindName(net0)));
|
||||
net0->TraceConnectWithoutContext("PhyTxBegin", MakeBoundCallback(&PhyTxBeginCallback, stream, Names::FindName(net0)));
|
||||
net1->TraceConnectWithoutContext("MacTx", MakeBoundCallback(&MacTxCallback, stream, Names::FindName(net1)));
|
||||
net1->TraceConnectWithoutContext("PhyTxBegin", MakeBoundCallback(&PhyTxBeginCallback, stream, Names::FindName(net1)));
|
||||
net2->TraceConnectWithoutContext("MacTx", MakeBoundCallback(&MacTxCallback, stream, Names::FindName(net2)));
|
||||
net2->TraceConnectWithoutContext("PhyTxBegin", MakeBoundCallback(&PhyTxBeginCallback, stream, Names::FindName(net2)));
|
||||
swnet0->TraceConnectWithoutContext("MacTx", MakeBoundCallback(&MacTxCallback, stream, Names::FindName(swnet0)));
|
||||
swnet0->TraceConnectWithoutContext("PhyTxBegin", MakeBoundCallback(&PhyTxBeginCallback, stream, Names::FindName(swnet0)));
|
||||
swnet1->TraceConnectWithoutContext("MacTx", MakeBoundCallback(&MacTxCallback, stream, Names::FindName(swnet1)));
|
||||
swnet1->TraceConnectWithoutContext("PhyTxBegin", MakeBoundCallback(&PhyTxBeginCallback, stream, Names::FindName(swnet1)));
|
||||
swnet2->TraceConnectWithoutContext("MacTx", MakeBoundCallback(&MacTxCallback, stream, Names::FindName(swnet2)));
|
||||
swnet2->TraceConnectWithoutContext("PhyTxBegin", MakeBoundCallback(&PhyTxBeginCallback, stream, Names::FindName(swnet2)));
|
||||
|
||||
|
||||
//Execute the simulation
|
||||
Simulator::Stop(Seconds(10));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
158
contrib/ethernet/examples/ethernet-switched.cc
Normal file
158
contrib/ethernet/examples/ethernet-switched.cc
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
|
||||
#include "ns3/ethernet-net-device.h"
|
||||
#include "ns3/ethernet-channel.h"
|
||||
#include "ns3/ethernet-generator.h"
|
||||
#include "ns3/ethernet-header2.h"
|
||||
#include "ns3/switch-net-device.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Example of the use of switch-net-device.cc switch-channel.cc
|
||||
* ethernet-net-device.cc ethernet-channel.cc on a network composed of three
|
||||
* end-stations connected with a 1Gb/s full duplex link
|
||||
* ES1 ==== SW ==== ES2
|
||||
* ==== ES3
|
||||
*/
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("Example");
|
||||
|
||||
//A callback to log the pkt reception
|
||||
static void
|
||||
MacRxCallback(std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << context << " : Pkt #" << p->GetUid() << " received !");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
//Enable logging
|
||||
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("EthernetGenerator", LOG_LEVEL_INFO);
|
||||
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
//Create four nodes
|
||||
Ptr<Node> n0 = CreateObject<Node>();
|
||||
Names::Add("ES1", n0);
|
||||
Ptr<Node> n1 = CreateObject<Node>();
|
||||
Names::Add("ES2", n1);
|
||||
Ptr<Node> n2 = CreateObject<Node>();
|
||||
Names::Add("ES3", n2);
|
||||
Ptr<Node> n3 = CreateObject<Node>();
|
||||
Names::Add("SW", n3);
|
||||
|
||||
//Create and add a netDevice to each end station node
|
||||
Ptr<EthernetNetDevice> net0 = CreateObject<EthernetNetDevice>();
|
||||
n0->AddDevice(net0);
|
||||
Names::Add("ES1#01", net0);
|
||||
Ptr<EthernetNetDevice> net1 = CreateObject<EthernetNetDevice>();
|
||||
n1->AddDevice(net1);
|
||||
Names::Add("ES2#01", net1);
|
||||
Ptr<EthernetNetDevice> net2 = CreateObject<EthernetNetDevice>();
|
||||
n2->AddDevice(net2);
|
||||
Names::Add("ES3#01", net2);
|
||||
|
||||
//Create and add a netDevice to each switch port
|
||||
Ptr<EthernetNetDevice> swnet0 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet0);
|
||||
Names::Add("SW#01", swnet0);
|
||||
Ptr<EthernetNetDevice> swnet1 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet1);
|
||||
Names::Add("SW#02", swnet1);
|
||||
Ptr<EthernetNetDevice> swnet2 = CreateObject<EthernetNetDevice>();
|
||||
n3->AddDevice(swnet2);
|
||||
Names::Add("SW#03", swnet2);
|
||||
|
||||
//Create Ethernet Channels and connect switch to the end-stations
|
||||
Ptr<EthernetChannel> channel0 = CreateObject<EthernetChannel>();
|
||||
net0->Attach(channel0);
|
||||
swnet0->Attach(channel0);
|
||||
Ptr<EthernetChannel> channel1 = CreateObject<EthernetChannel>();
|
||||
net1->Attach(channel1);
|
||||
swnet1->Attach(channel1);
|
||||
Ptr<EthernetChannel> channel2 = CreateObject<EthernetChannel>();
|
||||
net2->Attach(channel2);
|
||||
swnet2->Attach(channel2);
|
||||
|
||||
//Create and add a switch net device to the switch node
|
||||
Ptr<SwitchNetDevice> sw = CreateObject<SwitchNetDevice>();
|
||||
sw->SetAttribute("MinForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
sw->SetAttribute("MaxForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
n3->AddDevice(sw);
|
||||
sw->AddSwitchPort(swnet0);
|
||||
sw->AddSwitchPort(swnet1);
|
||||
sw->AddSwitchPort(swnet2);
|
||||
|
||||
//Allocate a Mac address and create 2 FIFOs (for the output port)
|
||||
//for each netDevice.
|
||||
net0->SetAddress(Mac48Address::Allocate());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net1->SetAddress(Mac48Address::Allocate());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net2->SetAddress(Mac48Address::Allocate());
|
||||
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
sw->SetAddress(Mac48Address::Allocate());
|
||||
swnet0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
swnet2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
//Add forwarding table
|
||||
sw->AddForwardingTableEntry(Mac48Address::ConvertFrom(net2->GetAddress()), 1, {swnet2});
|
||||
sw->AddForwardingTableEntry(Mac48Address("ff:ff:ff:ff:ff:ff"), 2, {swnet0, swnet2});
|
||||
|
||||
//Application descriptions
|
||||
//ES1 -> ES3 with priority 1
|
||||
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||||
app0->Setup(net0);
|
||||
app0->SetAttribute("Address", AddressValue(net2->GetAddress()));
|
||||
app0->SetAttribute("BurstSize", UintegerValue(2));
|
||||
app0->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app0->SetAttribute("Period", TimeValue(Seconds(5)));
|
||||
app0->SetAttribute("VlanID", UintegerValue(1));
|
||||
app0->SetAttribute("PCP", UintegerValue(1));
|
||||
n0->AddApplication(app0);
|
||||
app0->SetStartTime(Seconds(0));
|
||||
app0->SetStopTime(Seconds(5));
|
||||
|
||||
//ES2 -> ES1 and ES3 with priority 0
|
||||
Ptr<EthernetGenerator> app1 = CreateObject<EthernetGenerator>();
|
||||
app1->Setup(net1);
|
||||
app1->SetAttribute("Address", AddressValue(Mac48Address("ff:ff:ff:ff:ff:ff")));
|
||||
app1->SetAttribute("BurstSize", UintegerValue(1));
|
||||
app1->SetAttribute("PayloadSize", UintegerValue(1400));
|
||||
app1->SetAttribute("Period", TimeValue(Seconds(2.5)));
|
||||
app1->SetAttribute("VlanID", UintegerValue(2));
|
||||
app1->SetAttribute("PCP", UintegerValue(0));
|
||||
n1->AddApplication(app1);
|
||||
app1->SetStartTime(Seconds(0));
|
||||
app1->SetStopTime(Seconds(5));
|
||||
|
||||
//Callback to display the packet received log
|
||||
std::string context = Names::FindName(n0) + ":" + Names::FindName(net0);
|
||||
net0->TraceConnectWithoutContext("MacRx", MakeBoundCallback(&MacRxCallback, context));
|
||||
context = Names::FindName(n2) + ":" + Names::FindName(net2);
|
||||
net2->TraceConnectWithoutContext("MacRx", MakeBoundCallback(&MacRxCallback, context));
|
||||
|
||||
//Execute the simulation
|
||||
Simulator::Stop(Seconds(5));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
137
contrib/ethernet/model/ethernet-channel.cc
Normal file
137
contrib/ethernet/model/ethernet-channel.cc
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "ethernet-channel.h"
|
||||
#include "ethernet-net-device.h"
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("EthernetChannel");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(EthernetChannel);
|
||||
|
||||
TypeId
|
||||
EthernetChannel::GetTypeId()
|
||||
{
|
||||
static TypeId tid =
|
||||
TypeId("ns3::EthernetChannel")
|
||||
.SetParent<Channel>()
|
||||
.SetGroupName("Ethernet")
|
||||
.AddConstructor<EthernetChannel>()
|
||||
.AddAttribute("Delay",
|
||||
"Propagation delay through the channel",
|
||||
TimeValue(NanoSeconds(25)),
|
||||
MakeTimeAccessor(&EthernetChannel::m_delay),
|
||||
MakeTimeChecker())
|
||||
.AddTraceSource("TxRxEthernet",
|
||||
"Trace source indicating transmission of packet "
|
||||
"from the EthernetChannel, used by the Animation "
|
||||
"interface.",
|
||||
MakeTraceSourceAccessor(&EthernetChannel::m_txrxEthernet),
|
||||
"ns3::EthernetChannel::TxRxAnimationCallback");
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
EthernetChannel::EthernetChannel()
|
||||
: Channel(),
|
||||
m_nDevices(0)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
}
|
||||
|
||||
void
|
||||
EthernetChannel::Attach(Ptr<EthernetNetDevice> device)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << device);
|
||||
NS_ASSERT_MSG(m_nDevices < N_DEVICES, "Only two devices permitted");
|
||||
NS_ASSERT(device);
|
||||
|
||||
m_wire[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_wire[0].m_dst = m_wire[1].m_src;
|
||||
m_wire[1].m_dst = m_wire[0].m_src;
|
||||
m_wire[0].m_state = IDLE;
|
||||
m_wire[1].m_state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetChannel::TransmitStart(Ptr<const Packet> p, Ptr<EthernetNetDevice> src, Time txTime)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << p << src);
|
||||
NS_LOG_LOGIC("UID is " << p->GetUid() << ")");
|
||||
|
||||
NS_ASSERT(m_wire[0].m_state != INITIALIZING);
|
||||
NS_ASSERT(m_wire[1].m_state != INITIALIZING);
|
||||
|
||||
uint32_t wire = src == m_wire[0].m_src ? 0 : 1;
|
||||
|
||||
Simulator::ScheduleWithContext(m_wire[wire].m_dst->GetNode()->GetId(),
|
||||
txTime + m_delay,
|
||||
&EthernetNetDevice::Receive,
|
||||
m_wire[wire].m_dst,
|
||||
p->Copy());
|
||||
|
||||
// Call the tx anim callback on the net device
|
||||
m_txrxEthernet(p, src, m_wire[wire].m_dst, txTime, txTime + m_delay);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
EthernetChannel::GetNDevices() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return m_nDevices;
|
||||
}
|
||||
|
||||
Ptr<EthernetNetDevice>
|
||||
EthernetChannel::GetEthernetDevice(std::size_t i) const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
NS_ASSERT(i < 2);
|
||||
return m_wire[i].m_src;
|
||||
}
|
||||
|
||||
Ptr<NetDevice>
|
||||
EthernetChannel::GetDevice(std::size_t i) const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return GetEthernetDevice(i);
|
||||
}
|
||||
|
||||
Time
|
||||
EthernetChannel::GetDelay() const
|
||||
{
|
||||
return m_delay;
|
||||
}
|
||||
|
||||
Ptr<EthernetNetDevice>
|
||||
EthernetChannel::GetSource(uint32_t i) const
|
||||
{
|
||||
return m_wire[i].m_src;
|
||||
}
|
||||
|
||||
Ptr<EthernetNetDevice>
|
||||
EthernetChannel::GetDestination(uint32_t i) const
|
||||
{
|
||||
return m_wire[i].m_dst;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetChannel::IsInitialized() const
|
||||
{
|
||||
NS_ASSERT(m_wire[0].m_state != INITIALIZING);
|
||||
NS_ASSERT(m_wire[1].m_state != INITIALIZING);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
207
contrib/ethernet/model/ethernet-channel.h
Normal file
207
contrib/ethernet/model/ethernet-channel.h
Normal file
@@ -0,0 +1,207 @@
|
||||
#ifndef ETHERNET_CHANNEL_H
|
||||
#define ETHERNET_CHANNEL_H
|
||||
|
||||
#include "ns3/channel.h"
|
||||
#include "ns3/data-rate.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/traced-callback.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
// Add a doxygen group for this module.
|
||||
// If you have more than one file, this should be in only one of them.
|
||||
/**
|
||||
* \defgroup ethernet Description of the ethernet
|
||||
*/
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
class EthernetNetDevice;
|
||||
class Packet;
|
||||
|
||||
/**
|
||||
* \ingroup ethernet
|
||||
* \brief Simple Ethernet Channel.
|
||||
*
|
||||
* This class represents a very simple full duplex Ethernet channel. It is
|
||||
* largely inspired by the PointToPointChannel. There is no multi-drop
|
||||
* capability on this channel -- there can be a maximum of two Ethernet
|
||||
* net devices connected.
|
||||
*
|
||||
* There are two "wires" in the channel. The first device connected gets the
|
||||
* [0] wire to transmit on. The second device gets the [1] wire. There is a
|
||||
* state (IDLE, TRANSMITTING) associated with each wire.
|
||||
*
|
||||
* \see Attach
|
||||
* \see TransmitStart
|
||||
*/
|
||||
|
||||
class EthernetChannel : public Channel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the TypeId
|
||||
*
|
||||
* \return The TypeId for this class
|
||||
*/
|
||||
static TypeId GetTypeId();
|
||||
|
||||
/**
|
||||
* \brief Create a EthernetChannel
|
||||
*
|
||||
* By default, you get a channel that has a 25ns delay.
|
||||
*/
|
||||
EthernetChannel();
|
||||
|
||||
/**
|
||||
* \brief Attach a given netdevice to this channel
|
||||
* \param device pointer to the netdevice to attach to the channel
|
||||
*/
|
||||
void Attach(Ptr<EthernetNetDevice> device);
|
||||
|
||||
/**
|
||||
* \brief Transmit a packet over this channel
|
||||
* \param p Packet to transmit
|
||||
* \param src Source EthernetNetDevice
|
||||
* \param txTime Transmit time to apply
|
||||
* \returns true if successful (currently always true)
|
||||
*/
|
||||
virtual bool TransmitStart(Ptr<const Packet> p, Ptr<EthernetNetDevice> src, Time txTime);
|
||||
|
||||
/**
|
||||
* \brief Get number of devices on this channel
|
||||
* \returns number of devices on this channel
|
||||
*/
|
||||
std::size_t GetNDevices() const override;
|
||||
|
||||
/**
|
||||
* \brief Get EthernetNetDevice corresponding to index i on this channel
|
||||
* \param i Index number of the device requested
|
||||
* \returns Ptr to EthernetNetDevice requested
|
||||
*/
|
||||
Ptr<EthernetNetDevice> GetEthernetDevice(std::size_t i) const;
|
||||
|
||||
/**
|
||||
* \brief Get NetDevice corresponding to index i on this channel
|
||||
* \param i Index number of the device requested
|
||||
* \returns Ptr to NetDevice requested
|
||||
*/
|
||||
Ptr<NetDevice> GetDevice(std::size_t i) const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Get the delay associated with this channel
|
||||
* \returns Time delay
|
||||
*/
|
||||
Time GetDelay() const;
|
||||
|
||||
/**
|
||||
* \brief Check to make sure the wire is initialized
|
||||
* \returns true if initialized, asserts otherwise
|
||||
*/
|
||||
bool IsInitialized() const;
|
||||
|
||||
/**
|
||||
* \brief Get the net-device source
|
||||
* \param i the wire requested
|
||||
* \returns Ptr to EthernetNetDevice source for the
|
||||
* specified wire
|
||||
*/
|
||||
Ptr<EthernetNetDevice> GetSource(uint32_t i) const;
|
||||
|
||||
/**
|
||||
* \brief Get the net-device destination
|
||||
* \param i the wire requested
|
||||
* \returns Ptr to EthernetNetDevice destination for
|
||||
* the specified wire
|
||||
*/
|
||||
Ptr<EthernetNetDevice> GetDestination(uint32_t i) const;
|
||||
|
||||
/**
|
||||
* TracedCallback signature for packet transmission animation events.
|
||||
*
|
||||
* \param [in] packet The packet being transmitted.
|
||||
* \param [in] txDevice the TransmitTing NetDevice.
|
||||
* \param [in] rxDevice the Receiving NetDevice.
|
||||
* \param [in] duration The amount of time to transmit the packet.
|
||||
* \param [in] lastBitTime Last bit receive time (relative to now)
|
||||
* \deprecated The non-const \c Ptr<NetDevice> argument is deprecated
|
||||
* and will be changed to \c Ptr<const NetDevice> in a future release.
|
||||
*/
|
||||
typedef void (*TxRxAnimationCallback)(Ptr<const Packet> packet,
|
||||
Ptr<NetDevice> txDevice,
|
||||
Ptr<NetDevice> rxDevice,
|
||||
Time duration,
|
||||
Time lastBitTime);
|
||||
|
||||
private:
|
||||
/** Each ethernet full duplex wire has exactly two net devices. */
|
||||
static const std::size_t N_DEVICES = 2;
|
||||
|
||||
Time m_delay; //!< Propagation delay
|
||||
std::size_t m_nDevices; //!< Devices of this channel
|
||||
|
||||
/**
|
||||
* The trace source for the packet transmission animation events that the
|
||||
* device can fire.
|
||||
* Arguments to the callback are the packet, transmitting
|
||||
* net device, receiving net device, transmission time and
|
||||
* packet receipt time.
|
||||
*
|
||||
* \see class CallBackTraceSource
|
||||
* \deprecated The non-const \c Ptr<NetDevice> argument is deprecated
|
||||
* and will be changed to \c Ptr<const NetDevice> in a future release.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>, // Packet being transmitted
|
||||
Ptr<NetDevice>, // Transmitting NetDevice
|
||||
Ptr<NetDevice>, // Receiving NetDevice
|
||||
Time, // Amount of time to transmit the pkt
|
||||
Time // Last bit receive time (relative to now)
|
||||
>
|
||||
m_txrxEthernet;
|
||||
|
||||
/** \brief Wire states
|
||||
*
|
||||
*/
|
||||
enum WireState
|
||||
{
|
||||
/** Initializing state */
|
||||
INITIALIZING,
|
||||
/** Idle state (no transmission from NetDevice) */
|
||||
IDLE,
|
||||
/** Transmitting state (data being transmitted from NetDevice. */
|
||||
TRANSMITTING,
|
||||
/** Propagating state (data is being propagated in the channel. */
|
||||
PROPAGATING
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Wire model for the EthernetChannel
|
||||
*/
|
||||
class Wire
|
||||
{
|
||||
public:
|
||||
/** \brief Create the wire, it will be in INITIALIZING state
|
||||
*
|
||||
*/
|
||||
Wire()
|
||||
: m_state(INITIALIZING),
|
||||
m_src(nullptr),
|
||||
m_dst(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
WireState m_state; //!< State of the wire
|
||||
Ptr<EthernetNetDevice> m_src; //!< First NetDevice
|
||||
Ptr<EthernetNetDevice> m_dst; //!< Second NetDevice
|
||||
};
|
||||
|
||||
Wire m_wire[N_DEVICES]; //!< Wire model
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ETHERNET_CHANNEL_H */
|
||||
277
contrib/ethernet/model/ethernet-header2.cc
Normal file
277
contrib/ethernet/model/ethernet-header2.cc
Normal file
@@ -0,0 +1,277 @@
|
||||
#include "ethernet-header2.h"
|
||||
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/header.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/mac48-address.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
#include "ns3/address-utils.h"
|
||||
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("EthernetHeader2");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(EthernetHeader2);
|
||||
|
||||
EthernetHeader2::EthernetHeader2()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
}
|
||||
|
||||
EthernetHeader2::~EthernetHeader2()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
}
|
||||
|
||||
TypeId
|
||||
EthernetHeader2::GetTypeId()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
static TypeId tid = TypeId("ns3::EthernetHeader2")
|
||||
.SetParent<Header>()
|
||||
.SetGroupName("Ethernet")
|
||||
.AddConstructor<EthernetHeader2>();
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
EthernetHeader2::GetInstanceTypeId() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return GetTypeId();
|
||||
}
|
||||
|
||||
void
|
||||
EthernetHeader2::Print(std::ostream& os) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
std::string proto;
|
||||
|
||||
os << m_src << "->" << m_dest << " with ";
|
||||
for(int i=0; i<(int)m_QTagList.size(); i++)
|
||||
{
|
||||
if(m_QTagList[i].Type == VLAN)
|
||||
{
|
||||
os <<"vlan_id=" << (m_QTagList[i].TCI & 0xFFF) << " ";
|
||||
}
|
||||
if(m_QTagList[i].Type == REDUNDANCY)
|
||||
{
|
||||
os <<"RTAG=True ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
EthernetHeader2::GetSerializedSize() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
int tagSize = 0;
|
||||
for (int i=0; i<(int)m_QTagList.size(); i++)
|
||||
{
|
||||
if(m_QTagList[i].Type==VLAN)
|
||||
{
|
||||
tagSize += 4;
|
||||
}
|
||||
else if(m_QTagList[i].Type==REDUNDANCY)
|
||||
{
|
||||
tagSize += 6;
|
||||
}
|
||||
}
|
||||
return 6 + 6 + tagSize + 2;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetHeader2::Serialize(Buffer::Iterator start) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
Buffer::Iterator i = start;
|
||||
WriteTo(i, m_dest);
|
||||
WriteTo(i, m_src);
|
||||
|
||||
for (int j=0; j<(int)m_QTagList.size() ; j++)
|
||||
{
|
||||
i.WriteHtonU16(m_QTagList[j].TPID);
|
||||
if(m_QTagList[j].Type == VLAN)
|
||||
{
|
||||
i.WriteHtonU16(m_QTagList[j].TCI);
|
||||
}
|
||||
else if(m_QTagList[j].Type == REDUNDANCY)
|
||||
{
|
||||
i.WriteHtonU32(m_QTagList[j].TCI);
|
||||
}
|
||||
}
|
||||
i.WriteHtonU16(m_ethertype);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
EthernetHeader2::Deserialize(Buffer::Iterator start)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
Buffer::Iterator i = start;
|
||||
ReadFrom(i, m_dest);
|
||||
ReadFrom(i, m_src);
|
||||
uint16_t tmp = i.ReadNtohU16();
|
||||
while (tmp==0x8100 or tmp==0xf1c1){
|
||||
TagType type = VLAN;
|
||||
uint32_t tci = 0;
|
||||
|
||||
if (tmp==0x8100){
|
||||
type = VLAN;
|
||||
tci = i.ReadNtohU16();
|
||||
}
|
||||
else if (tmp==0xf1c1){
|
||||
type = REDUNDANCY;
|
||||
tci = i.ReadNtohU32();
|
||||
}
|
||||
Qtag entry = {tmp, tci, type};
|
||||
m_QTagList.insert(m_QTagList.end(), entry);
|
||||
tmp = i.ReadNtohU16();
|
||||
}
|
||||
m_ethertype = tmp;
|
||||
|
||||
// NS_LOG_INFO("m_QTagList size = " << m_QTagList.size());
|
||||
return GetSerializedSize();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EthernetHeader2::SetDest(Mac48Address addr)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_dest = addr;
|
||||
}
|
||||
|
||||
Mac48Address
|
||||
EthernetHeader2::GetDest()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_dest;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetHeader2::SetSrc(Mac48Address addr)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_src = addr;
|
||||
}
|
||||
|
||||
Mac48Address
|
||||
EthernetHeader2::GetSrc()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_src;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
EthernetHeader2::GetPcp()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
for(int i=0; i<(int)m_QTagList.size(); i++)
|
||||
{
|
||||
if(m_QTagList[i].Type == VLAN)
|
||||
{
|
||||
return (m_QTagList[i].TCI >> 13) & 0x7;
|
||||
}
|
||||
}
|
||||
NS_ASSERT_MSG(true, "Can't find a Vlan QTag in this header");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
EthernetHeader2::GetDei()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
for(int i=0; i<(int)m_QTagList.size(); i++)
|
||||
{
|
||||
if(m_QTagList[i].Type == VLAN)
|
||||
{
|
||||
return uint8_t((m_QTagList[i].TCI >> 12) & 0x1);
|
||||
}
|
||||
}
|
||||
NS_ASSERT_MSG(true, "Can't find a Vlan QTag in this header");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
EthernetHeader2::GetVid()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
for(int i=0; i<(int)m_QTagList.size(); i++)
|
||||
{
|
||||
if(m_QTagList[i].Type == VLAN)
|
||||
{
|
||||
return (m_QTagList[i].TCI & 0xFFF);
|
||||
}
|
||||
}
|
||||
NS_ASSERT_MSG(true, "Can't find a Vlan QTag in this header");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetHeader2::SetEthertype(uint16_t ethertype)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_ethertype = ethertype;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
EthernetHeader2::GetEthertype()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_ethertype;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetHeader2::SetVlanTag(uint8_t pcp, uint8_t dei, uint16_t vid)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
NS_ASSERT_MSG(vid < 4096 , "Vlan id must be between 0 and 4095");
|
||||
NS_ASSERT_MSG(dei < 2 , "DEI must be between 0 and 1");
|
||||
NS_ASSERT_MSG(pcp < 8 , "PCP must be between 0 and 7");
|
||||
|
||||
uint16_t tpid = 0x8100;
|
||||
uint32_t tci = (pcp << 13) | (dei << 12) | vid;
|
||||
Qtag entry = {tpid, tci, VLAN};
|
||||
m_QTagList.insert(m_QTagList.begin(), entry);
|
||||
}
|
||||
|
||||
void
|
||||
EthernetHeader2::SetRedundancyTag(uint16_t seqNum)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
uint16_t tpid = 0xf1c1;
|
||||
uint32_t tci = (0 << 16) | seqNum;
|
||||
Qtag entry = {tpid, tci, REDUNDANCY};
|
||||
m_QTagList.insert(m_QTagList.begin(), entry);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
EthernetHeader2::RemoveRedundancyTag()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
for (int i=0; i<(int)m_QTagList.size(); i++)
|
||||
{
|
||||
if(m_QTagList[i].Type == REDUNDANCY)
|
||||
{
|
||||
uint16_t seqNum = m_QTagList[i].TCI & 0xFFFF;
|
||||
m_QTagList.erase(m_QTagList.begin() + i);
|
||||
return seqNum;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERT_MSG(true, "Can't find a Redundancy QTag in this header");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
86
contrib/ethernet/model/ethernet-header2.h
Normal file
86
contrib/ethernet/model/ethernet-header2.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#ifndef ETHERNET_HEADER2_H
|
||||
#define ETHERNET_HEADER2_H
|
||||
|
||||
#include "ns3/header.h"
|
||||
#include "ns3/mac48-address.h"
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
/**
|
||||
* \ingroup ethernet
|
||||
* \brief Packet header for Ethernet
|
||||
*
|
||||
* This class can be used to add a header to Ethernet packet.
|
||||
*/
|
||||
|
||||
class EthernetHeader2 : public Header
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Construct a Ethernet header.
|
||||
*/
|
||||
EthernetHeader2();
|
||||
|
||||
/**
|
||||
* \brief Destroy a Ethernet header.
|
||||
*/
|
||||
~EthernetHeader2() override;
|
||||
|
||||
/**
|
||||
* \brief Get the TypeId
|
||||
*
|
||||
* \return The TypeId for this class
|
||||
*/
|
||||
static TypeId GetTypeId();
|
||||
|
||||
/**
|
||||
* \brief Get the TypeId of the instance
|
||||
*
|
||||
* \return The TypeId for this instance
|
||||
*/
|
||||
TypeId GetInstanceTypeId() const override;
|
||||
|
||||
void Print(std::ostream& os) const override;
|
||||
void Serialize(Buffer::Iterator start) const override;
|
||||
uint32_t Deserialize(Buffer::Iterator start) override;
|
||||
uint32_t GetSerializedSize() const override;
|
||||
|
||||
void SetDest(Mac48Address addr);
|
||||
Mac48Address GetDest();
|
||||
void SetSrc(Mac48Address addr);
|
||||
Mac48Address GetSrc();
|
||||
uint8_t GetPcp();
|
||||
uint8_t GetDei();
|
||||
uint16_t GetVid();
|
||||
void SetEthertype(uint16_t ethertype);
|
||||
uint16_t GetEthertype();
|
||||
|
||||
void SetVlanTag(uint8_t pcp, uint8_t dei, uint16_t vid);
|
||||
void SetRedundancyTag(uint16_t seqNum);
|
||||
uint16_t RemoveRedundancyTag();
|
||||
|
||||
|
||||
private:
|
||||
Mac48Address m_dest;
|
||||
Mac48Address m_src;
|
||||
|
||||
//QTag (VlanTag, RedundancyTag ...)
|
||||
enum TagType
|
||||
{
|
||||
VLAN,
|
||||
REDUNDANCY,
|
||||
};
|
||||
struct Qtag
|
||||
{
|
||||
uint16_t TPID; //Tag Protocol Identifier
|
||||
uint32_t TCI; //Tag Control Information
|
||||
TagType Type;
|
||||
};
|
||||
|
||||
std::vector<Qtag> m_QTagList;
|
||||
|
||||
uint16_t m_ethertype;
|
||||
};
|
||||
|
||||
} // namespace eden
|
||||
#endif /* ETHERNET_HEADER2_H */
|
||||
769
contrib/ethernet/model/ethernet-net-device.cc
Normal file
769
contrib/ethernet/model/ethernet-net-device.cc
Normal file
@@ -0,0 +1,769 @@
|
||||
#include "ethernet-net-device.h"
|
||||
|
||||
#include "ethernet-channel.h"
|
||||
#include "ethernet-header2.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/ethernet-trailer.h"
|
||||
#include "ns3/timestamp-tag.h"
|
||||
#include "ns3/names.h"
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("EthernetNetDevice");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(EthernetNetDevice);
|
||||
|
||||
TypeId
|
||||
EthernetNetDevice::GetTypeId()
|
||||
{
|
||||
static TypeId tid =
|
||||
TypeId("ns3::EthernetNetDevice")
|
||||
.SetParent<NetDevice>()
|
||||
.SetGroupName("Ethernet")
|
||||
.AddConstructor<EthernetNetDevice>()
|
||||
.AddAttribute("Mtu",
|
||||
"The MAC-level Maximum Transmission Unit",
|
||||
UintegerValue(DEFAULT_MTU),
|
||||
MakeUintegerAccessor(&EthernetNetDevice::SetMtu,
|
||||
&EthernetNetDevice::GetMtu),
|
||||
MakeUintegerChecker<uint16_t>())
|
||||
.AddAttribute("Address",
|
||||
"The MAC address of this device.",
|
||||
Mac48AddressValue(Mac48Address("00:00:00:00:ED:E1")),
|
||||
MakeMac48AddressAccessor(&EthernetNetDevice::m_address),
|
||||
MakeMac48AddressChecker())
|
||||
.AddAttribute("DataRate",
|
||||
"The default data rate for point to point links",
|
||||
DataRateValue(DataRate("1Gb/s")),
|
||||
MakeDataRateAccessor(&EthernetNetDevice::m_bps),
|
||||
MakeDataRateChecker())
|
||||
.AddAttribute("ReceiveErrorModel",
|
||||
"The receiver error model used to simulate packet loss",
|
||||
PointerValue(),
|
||||
MakePointerAccessor(&EthernetNetDevice::m_receiveErrorModel),
|
||||
MakePointerChecker<ErrorModel>())
|
||||
.AddAttribute("preambleAndSFDGap",
|
||||
"Number of byte for the preamble and start of frame delimiter gap",
|
||||
UintegerValue(8),
|
||||
MakeUintegerAccessor(&EthernetNetDevice::m_preambleAndSFDGap),
|
||||
MakeUintegerChecker<uint8_t>())
|
||||
.AddAttribute("InterframeGap",
|
||||
"Number of byte for the interframe gap",
|
||||
UintegerValue(12),
|
||||
MakeUintegerAccessor(&EthernetNetDevice::m_interframeGap),
|
||||
MakeUintegerChecker<uint8_t>())
|
||||
|
||||
//
|
||||
// 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(&EthernetNetDevice::m_macTxTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("MacTxAnimation",
|
||||
"Trace source indicating a packet has arrived "
|
||||
"for transmission by this device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_macTxAnimationTrace),
|
||||
"ns3::EthernetNetDevice::MacTxAnimationCallback")
|
||||
.AddTraceSource("MacTxDrop",
|
||||
"Trace source indicating a packet has been dropped "
|
||||
"by the device before transmission",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::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(&EthernetNetDevice::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(&EthernetNetDevice::m_macRxTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("MacRxAnimation",
|
||||
"Trace source indicating a packet has arrived "
|
||||
"in this device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_macRxAnimationTrace),
|
||||
"ns3::EthernetNetDevice::MacRxAnimationCallback")
|
||||
#if 0
|
||||
// Not currently implemented for this device
|
||||
.AddTraceSource ("MacRxDrop",
|
||||
"Trace source indicating a packet was dropped "
|
||||
"before being forwarded up the stack",
|
||||
MakeTraceSourceAccessor (&EthernetNetDevice::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(&EthernetNetDevice::m_phyTxBeginTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("PhyTxEnd",
|
||||
"Trace source indicating a packet has been "
|
||||
"completely transmitted over the channel",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_phyTxEndTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("PhyTxDrop",
|
||||
"Trace source indicating a packet has been "
|
||||
"dropped by the device during transmission",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_phyTxDropTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("Latency",
|
||||
"Trace source to compute network latency ",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_latencyTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("FIFOState",
|
||||
"Trace source to study the FIFO state ",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_FIFOStateSnifferTrace),
|
||||
"ns3::EthernetNetDevice::m_FIFOStateSnifferTrace")
|
||||
#if 0
|
||||
// Not currently implemented for this device
|
||||
.AddTraceSource ("PhyRxBegin",
|
||||
"Trace source indicating a packet has begun "
|
||||
"being received by the device",
|
||||
MakeTraceSourceAccessor (&EthernetNetDevice::m_phyRxBeginTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
#endif
|
||||
.AddTraceSource("PhyRxEnd",
|
||||
"Trace source indicating a packet has been "
|
||||
"completely received by the device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_phyRxEndTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("PhyRxDrop",
|
||||
"Trace source indicating a packet has been "
|
||||
"dropped by the device during reception",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::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(&EthernetNetDevice::m_snifferTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("PromiscSniffer",
|
||||
"Trace source simulating a promiscuous packet sniffer "
|
||||
"attached to the device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_promiscSnifferTrace),
|
||||
"ns3::Packet::TracedCallback");
|
||||
return tid;
|
||||
}
|
||||
|
||||
EthernetNetDevice::EthernetNetDevice()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_txMachineState = READY;
|
||||
m_channel = nullptr;
|
||||
m_linkUp = false;
|
||||
m_currentPkt = nullptr;
|
||||
}
|
||||
|
||||
EthernetNetDevice::~EthernetNetDevice()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::AddHeader(Ptr<Packet> p, Mac48Address dst, Mac48Address src, uint16_t ethertype)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
EthernetHeader2 ethHeader;
|
||||
ethHeader.SetDest(dst);
|
||||
ethHeader.SetSrc(src);
|
||||
ethHeader.SetEthertype(ethertype);
|
||||
p->AddHeader(ethHeader);
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::AddHeader(Ptr<Packet> p, Mac48Address dst, Mac48Address src, uint16_t ethertype, uint16_t vid, uint8_t pcp, uint8_t dei)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
EthernetHeader2 ethHeader;
|
||||
ethHeader.SetDest(dst);
|
||||
ethHeader.SetSrc(src);
|
||||
ethHeader.SetEthertype(ethertype);
|
||||
ethHeader.SetVlanTag(pcp, dei, vid);
|
||||
p->AddHeader(ethHeader);
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::DoDispose()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_node = nullptr;
|
||||
m_channel = nullptr;
|
||||
m_receiveErrorModel = nullptr;
|
||||
m_currentPkt = nullptr;
|
||||
m_queues.clear();
|
||||
NetDevice::DoDispose();
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetDataRate(DataRate bps)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_bps = bps;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::TransmitStart(Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << p);
|
||||
NS_ASSERT_MSG(m_channel != nullptr, "Channel ptr is null");
|
||||
|
||||
NS_LOG_INFO(Names::FindName(this) << " PKT #" << p->GetUid() << " at " << Simulator::Now().GetNanoSeconds()<<" Transmit started ");
|
||||
|
||||
//Add a tag to compute delay between reception(or FIFO enter if first
|
||||
//emission port) and transmission start
|
||||
TimestampTag tag(Simulator::Now());
|
||||
p->AddByteTag(tag);
|
||||
|
||||
//
|
||||
// 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 preambleAndSFDGapTime = m_bps.CalculateBytesTxTime(m_preambleAndSFDGap);
|
||||
Time txTime = m_bps.CalculateBytesTxTime(p->GetSize());
|
||||
Time interpacketGapTime = m_bps.CalculateBytesTxTime(m_interframeGap);
|
||||
Time txCompleteTime = preambleAndSFDGapTime + txTime + interpacketGapTime;
|
||||
|
||||
//NS_LOG_INFO(Names::FindName(this) << " "<< Simulator::Now().GetNanoSeconds()<<" Transmit pkt #"<<p->GetUid());
|
||||
//NS_LOG_LOGIC(Names::FindName(this) << " Schedule TransmitCompleteEvent in " << txCompleteTime.As(Time::S) << " for PKT #" << p->GetUid());
|
||||
Simulator::Schedule(txCompleteTime, &EthernetNetDevice::TransmitComplete, this);
|
||||
|
||||
bool result = m_channel->TransmitStart(p, this, txCompleteTime-interpacketGapTime); //Pkt don't need to wait for the end of Interpacket gap to be considered as receive on the other end of the link
|
||||
if (!result)
|
||||
{
|
||||
m_phyTxDropTrace(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::TransmitComplete()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
NS_LOG_INFO(Names::FindName(this) << " PKT #" << m_currentPkt->GetUid() << " at " << Simulator::Now().GetNanoSeconds()<<" Transmit completed ");
|
||||
// NS_LOG_INFO(Names::FindName(this) << " "<< Simulator::Now().GetNanoSeconds()<<" Transmit completed pkt ");
|
||||
//
|
||||
// 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, "EthernetNetDevice::TransmitComplete(): m_currentPkt zero");
|
||||
|
||||
m_phyTxEndTrace(m_currentPkt);
|
||||
|
||||
m_currentPkt = nullptr;
|
||||
|
||||
//Add the event after all the already present at this exact instant to avoid
|
||||
//the beginning of a transmission if a packet will be ready at the event just
|
||||
//after but at the same time instant.
|
||||
Simulator::Schedule(Time(0), &EthernetNetDevice::CheckForReadyPacket, this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EthernetNetDevice::CheckForReadyPacket()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
if (m_txMachineState != READY){
|
||||
return;
|
||||
}
|
||||
|
||||
int next_queue_id = TransmitSelection();
|
||||
if(next_queue_id==-1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Ptr<Packet> p = m_queues[next_queue_id]->Dequeue();
|
||||
//
|
||||
// Got another packet off of the queue, so start the transmit process again.
|
||||
//
|
||||
m_snifferTrace(p);
|
||||
m_promiscSnifferTrace(p);
|
||||
TransmitStart(p);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
EthernetNetDevice::TransmitSelection()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
//For now simple Static Priority Algo
|
||||
for (int i = m_queues.size(); i --> 0; )
|
||||
{
|
||||
if(!m_queues[i]->IsEmpty())
|
||||
{
|
||||
return(i);
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EthernetNetDevice::Attach(Ptr<EthernetChannel> 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;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetQueue(Ptr<Queue<Packet>> q)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << q);
|
||||
m_queues.insert(m_queues.end(),q);
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetReceiveErrorModel(Ptr<ErrorModel> em)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << em);
|
||||
m_receiveErrorModel = em;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::Receive(Ptr<Packet> packet)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << packet);
|
||||
NS_LOG_LOGIC("UID is " << packet->GetUid());
|
||||
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.
|
||||
//
|
||||
NS_LOG_LOGIC("Dropping pkt due to error model ");
|
||||
m_phyRxDropTrace(packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Add timestamp to measure delay in the switches
|
||||
TimestampTag tag(Simulator::Now());
|
||||
packet->AddByteTag(tag);
|
||||
//
|
||||
// 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<Packet> originalPacket = packet->Copy();
|
||||
|
||||
EthernetTrailer trailer;
|
||||
packet->RemoveTrailer(trailer);
|
||||
if (Node::ChecksumEnabled())
|
||||
{
|
||||
trailer.EnableFcs(true);
|
||||
}
|
||||
|
||||
bool crcGood = trailer.CheckFcs(packet);
|
||||
if (!crcGood)
|
||||
{
|
||||
NS_LOG_INFO("CRC error on Packet " << packet);
|
||||
m_phyRxDropTrace(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Strip off the ethernet 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.
|
||||
//
|
||||
EthernetHeader2 header;
|
||||
packet->RemoveHeader(header);
|
||||
|
||||
uint16_t protocol;
|
||||
protocol = header.GetEthertype();
|
||||
|
||||
//
|
||||
// Classify the packet based on its destination.
|
||||
//
|
||||
PacketType packetType;
|
||||
|
||||
if (header.GetDest() == m_address)
|
||||
{
|
||||
packetType = PACKET_HOST;
|
||||
}
|
||||
else if (header.GetDest().IsGroup())
|
||||
{
|
||||
packetType = PACKET_MULTICAST;
|
||||
}
|
||||
else if (header.GetDest().IsBroadcast())
|
||||
{
|
||||
packetType = PACKET_BROADCAST;
|
||||
}
|
||||
else
|
||||
{
|
||||
packetType = PACKET_OTHERHOST;
|
||||
}
|
||||
|
||||
if (!m_promiscCallback.IsNull())
|
||||
{
|
||||
m_macPromiscRxTrace(originalPacket->Copy());
|
||||
m_promiscCallback(this,
|
||||
originalPacket,
|
||||
protocol,
|
||||
header.GetSrc(),
|
||||
header.GetDest(),
|
||||
packetType);
|
||||
}
|
||||
//
|
||||
// If this packet is not destined for some other host, it must be for us
|
||||
// as either a broadcast, multicast or unicast. We need to hit the mac
|
||||
// packet received trace hook and forward the packet up the stack.
|
||||
//
|
||||
if (packetType != PACKET_OTHERHOST)
|
||||
{
|
||||
//NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << Names::FindName(m_node) << "/" << Names::FindName(this) <<" : Pkt #" << originalPacket->GetUid() <<" received by the netDevice ! " << originalPacket->ToString());
|
||||
m_macRxTrace(originalPacket);
|
||||
m_macRxAnimationTrace(originalPacket, this);
|
||||
m_rxCallback(this, packet, protocol, header.GetSrc());
|
||||
m_latencyTrace(originalPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<Queue<Packet>>
|
||||
EthernetNetDevice::GetQueue(uint8_t index) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_queues[index];
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::NotifyLinkUp()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_linkUp = true;
|
||||
m_linkChangeCallbacks();
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetIfIndex(const uint32_t index)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_ifIndex = index;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
EthernetNetDevice::GetIfIndex() const
|
||||
{
|
||||
return m_ifIndex;
|
||||
}
|
||||
|
||||
Ptr<Channel>
|
||||
EthernetNetDevice::GetChannel() const
|
||||
{
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetAddress(Address address)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << address);
|
||||
m_address = Mac48Address::ConvertFrom(address);
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetAddress() const
|
||||
{
|
||||
return m_address;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EthernetNetDevice::IsLinkUp() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_linkUp;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::AddLinkChangeCallback(Callback<void> callback)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_linkChangeCallbacks.ConnectWithoutContext(callback);
|
||||
}
|
||||
|
||||
//
|
||||
// This is a ethernet device, so every transmission is a broadcast to
|
||||
// all of the devices on the channel.
|
||||
//
|
||||
bool
|
||||
EthernetNetDevice::IsBroadcast() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetBroadcast() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return Mac48Address("ff:ff:ff:ff:ff:ff");
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::IsMulticast() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetMulticast(Ipv4Address multicastGroup) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return Mac48Address("01:00:5e:00:00:00");
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetMulticast(Ipv6Address addr) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this << addr);
|
||||
return Mac48Address("33:33:00:00:00:00");
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::IsPointToPoint() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::IsBridge() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EthernetNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t ethertype)
|
||||
{
|
||||
uint16_t vid = 65535;
|
||||
uint8_t pcp = 0;
|
||||
uint8_t dei = 0;
|
||||
return SendFrom(packet, GetAddress(), dest, ethertype, vid, pcp, dei);
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t ethertype, uint16_t vid, uint8_t pcp, uint8_t dei)
|
||||
{
|
||||
return SendFrom(packet, GetAddress(), dest, ethertype, vid, pcp, dei);
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::SendFrom(Ptr<Packet> packet,
|
||||
const Address& source,
|
||||
const Address& dest,
|
||||
uint16_t ethertype)
|
||||
{
|
||||
//Call by the switch net device with a packet with a EhternetHeader2 and EthernetTrailer
|
||||
//Or by another SendFrom function that have already have a packet with header and trailer
|
||||
// /!\ source, dest, and ethertype are not use in this function but are needed in
|
||||
// the callback define by the netDevice class
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
//Add timestamp if first emission
|
||||
TimestampTag tag(Simulator::Now());
|
||||
if (!packet->FindFirstMatchingByteTag(tag))
|
||||
{
|
||||
packet->AddByteTag(tag);
|
||||
}
|
||||
m_macTxTrace(packet);
|
||||
m_macTxAnimationTrace(packet, this);
|
||||
|
||||
Ptr<Packet> pCopy = packet->Copy();
|
||||
EthernetHeader2 header;
|
||||
pCopy->RemoveHeader(header);
|
||||
uint8_t pcp = header.GetPcp();
|
||||
|
||||
NS_ASSERT_MSG(m_queues.size() > pcp, "Not enough fifos ( 0 to "<< m_queues.size()-1 <<") to handle this pcp priority ("<< unsigned(pcp) <<") on Node " <<Names::FindName(GetNode()));
|
||||
|
||||
|
||||
m_FIFOStateSnifferTrace(m_queues, m_txMachineState==BUSY, packet);
|
||||
//
|
||||
// We should enqueue and dequeue the packet to hit the tracing hooks.
|
||||
//
|
||||
if (m_queues[pcp]->Enqueue(packet))
|
||||
{
|
||||
NS_LOG_INFO(Names::FindName(this) << " Enqueue pkt #"<<packet->GetUid() << " OK !");
|
||||
//Add the event after all the already present at this exact instant to avoid
|
||||
//the beginning of a transmission if a packet will be ready at the event just
|
||||
//after but at the same time instant.
|
||||
Simulator::Schedule(Time(0), &EthernetNetDevice::CheckForReadyPacket, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Enqueue may fail (overflow)
|
||||
m_macTxDropTrace(packet);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t ethertype, uint16_t vid, uint8_t pcp, uint8_t dei)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << packet << dest << ethertype);
|
||||
NS_LOG_LOGIC(Names::FindName(this) << " p=" << packet->GetUid() << ", dest=" << &dest);
|
||||
|
||||
// NS_LOG_INFO(Names::FindName(this) << " SendFrom : p=" << packet->GetUid() << ", dest=" << &dest << " at " << Simulator::Now());
|
||||
|
||||
|
||||
if (vid == 65535){
|
||||
AddHeader(packet, Mac48Address::ConvertFrom(dest), Mac48Address::ConvertFrom(source), ethertype);
|
||||
}
|
||||
else{
|
||||
AddHeader(packet, Mac48Address::ConvertFrom(dest), Mac48Address::ConvertFrom(source), ethertype, vid, pcp, dei);
|
||||
}
|
||||
|
||||
EthernetTrailer trailer;
|
||||
trailer.EnableFcs(true);
|
||||
trailer.CalcFcs(packet);
|
||||
packet->AddTrailer(trailer);
|
||||
|
||||
|
||||
return SendFrom(packet, source, dest, ethertype);
|
||||
}
|
||||
|
||||
Ptr<Node>
|
||||
EthernetNetDevice::GetNode() const
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetNode(Ptr<Node> node)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_node = node;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::NeedsArp() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb)
|
||||
{
|
||||
m_rxCallback = cb;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
|
||||
{
|
||||
m_promiscCallback = cb;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::SupportsSendFrom() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetRemote() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
NS_ASSERT(m_channel->GetNDevices() == 2);
|
||||
for (std::size_t i = 0; i < m_channel->GetNDevices(); ++i)
|
||||
{
|
||||
Ptr<NetDevice> tmp = m_channel->GetDevice(i);
|
||||
if (tmp != this)
|
||||
{
|
||||
return tmp->GetAddress();
|
||||
}
|
||||
}
|
||||
NS_ASSERT(false);
|
||||
// quiet compiler.
|
||||
return Address();
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::SetMtu(uint16_t mtu)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << mtu);
|
||||
m_mtu = mtu;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
EthernetNetDevice::GetMtu() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_mtu;
|
||||
}
|
||||
|
||||
}
|
||||
464
contrib/ethernet/model/ethernet-net-device.h
Normal file
464
contrib/ethernet/model/ethernet-net-device.h
Normal file
@@ -0,0 +1,464 @@
|
||||
#ifndef ETHERNET_NET_DEVICE_H
|
||||
#define ETHERNET_NET_DEVICE_H
|
||||
|
||||
#include "ns3/address.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/data-rate.h"
|
||||
#include "ns3/mac48-address.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/net-device.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
class EthernetChannel;
|
||||
class ErrorModel;
|
||||
|
||||
/**
|
||||
* \ingroup ethernet
|
||||
* \class EthernetNetDevice
|
||||
* \brief A Device for a Ethernet full duplex Link.
|
||||
*
|
||||
* This EthernetNetDevice class specializes the NetDevice abstract
|
||||
* base class. Together with a EthernetChannel (and a peer
|
||||
* EthernetNetDevice), the class models, with some level of
|
||||
* abstraction, a full duplex ethernet link.
|
||||
* Key parameters or objects that can be specified for this device
|
||||
* include a queue, data rate, and interframe transmission gap (the
|
||||
* propagation delay is set in the EthernetChannel).
|
||||
*/
|
||||
|
||||
class EthernetNetDevice : public NetDevice
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the TypeId
|
||||
*
|
||||
* \return The TypeId for this class
|
||||
*/
|
||||
static TypeId GetTypeId();
|
||||
|
||||
/**
|
||||
* Construct a EthernetNetDevice
|
||||
*
|
||||
* This is the constructor for the EthernetNetDevice. It takes as a
|
||||
* parameter a pointer to the Node to which this device is connected,
|
||||
* as well as an optional DataRate object.
|
||||
*/
|
||||
EthernetNetDevice();
|
||||
|
||||
/**
|
||||
* Destroy a EthernetNetDevice
|
||||
*
|
||||
* This is the destructor for the EthernetNetDevice.
|
||||
*/
|
||||
~EthernetNetDevice() override;
|
||||
|
||||
// Delete copy constructor and assignment operator to avoid misuse
|
||||
EthernetNetDevice& operator=(const EthernetNetDevice&) = delete;
|
||||
EthernetNetDevice(const EthernetNetDevice&) = delete;
|
||||
|
||||
/**
|
||||
* Set the Data Rate used for transmission of packets. The data rate is
|
||||
* set in the Attach () method from the corresponding field in the channel
|
||||
* to which the device is attached. It can be overridden using this method.
|
||||
*
|
||||
* \param bps the data rate at which this object operates
|
||||
*/
|
||||
void SetDataRate(DataRate bps);
|
||||
|
||||
/**
|
||||
* Attach the device to a channel.
|
||||
*
|
||||
* \param ch Ptr to the channel to which this object is being attached.
|
||||
* \return true if the operation was successful (always true actually)
|
||||
*/
|
||||
bool Attach(Ptr<EthernetChannel> ch);
|
||||
|
||||
/**
|
||||
* Attach a queue to the EthernetNetDevice.
|
||||
*
|
||||
* The EthernetNetDevice "owns" a queue that implements a queueing
|
||||
* method such as DropTailQueue or RedQueue
|
||||
*
|
||||
* \param queue Ptr to the new queue.
|
||||
*/
|
||||
void SetQueue(Ptr<Queue<Packet>> queue);
|
||||
|
||||
/**
|
||||
* Get a copy of the attached Queue.
|
||||
*
|
||||
* \param index Queue index
|
||||
* \returns Ptr to the queue.
|
||||
*/
|
||||
Ptr<Queue<Packet>> GetQueue(uint8_t index) const;
|
||||
|
||||
/**
|
||||
* Attach a receive ErrorModel to the EthernetNetDevice.
|
||||
*
|
||||
* The EthernetNetDevice may optionally include an ErrorModel in
|
||||
* the packet receive chain.
|
||||
*
|
||||
* \param em Ptr to the ErrorModel.
|
||||
*/
|
||||
void SetReceiveErrorModel(Ptr<ErrorModel> em);
|
||||
|
||||
/**
|
||||
* Receive a packet from a connected EthernetNetDevice.
|
||||
*
|
||||
* The EthernetNetDevice receives packets from its connected channel
|
||||
* and forwards them up the protocol stack. This is the public method
|
||||
* used by the channel to indicate that the last bit of a packet has
|
||||
* arrived at the device.
|
||||
*
|
||||
* \param p Ptr to the received packet.
|
||||
*/
|
||||
virtual void Receive(Ptr<Packet> p);
|
||||
|
||||
// The remaining methods are documented in ns3::NetDevice*
|
||||
|
||||
void SetIfIndex(const uint32_t index) override;
|
||||
uint32_t GetIfIndex() const override;
|
||||
|
||||
Ptr<Channel> 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<void> 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> packet, const Address& dest, uint16_t ethertype) override;
|
||||
bool Send(Ptr<Packet> packet, const Address& dest, uint16_t ethertype, uint16_t vid, uint8_t pcp, uint8_t dei);
|
||||
virtual bool SendFrom(Ptr<Packet> packet,
|
||||
const Address& source,
|
||||
const Address& dest,
|
||||
uint16_t ethertype) override;
|
||||
bool SendFrom(Ptr<Packet> packet,
|
||||
const Address& source,
|
||||
const Address& dest,
|
||||
uint16_t ethertype,
|
||||
uint16_t vid,
|
||||
uint8_t pcp,
|
||||
uint8_t dei);
|
||||
|
||||
Ptr<Node> GetNode() const override;
|
||||
void SetNode(Ptr<Node> 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;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Dispose of the object
|
||||
*/
|
||||
void DoDispose() override;
|
||||
|
||||
/**
|
||||
* \returns the address of the remote device connected to this device
|
||||
* through the ethernet channel.
|
||||
*/
|
||||
Address GetRemote() const;
|
||||
|
||||
/**
|
||||
* Adds the necessary headers and trailers to a packet of data in order to
|
||||
* respect the protocol implemented by the agent.
|
||||
* \param p packet
|
||||
* \param dst Dst mac address
|
||||
* \param src Src mac address
|
||||
* \param ethertype ethertype
|
||||
*/
|
||||
void AddHeader(Ptr<Packet> p, Mac48Address dst, Mac48Address src, uint16_t ethertype);
|
||||
|
||||
/**
|
||||
* Adds the necessary headers to a packet of data in order to
|
||||
* respect the protocol implemented by the agent.
|
||||
* \param p packet
|
||||
* \param dst Dst mac address
|
||||
* \param src Src mac address
|
||||
* \param ethertype ethertype
|
||||
* \param vid vlain id
|
||||
* \param pcp pcp field
|
||||
* \param dei dei bit
|
||||
*/
|
||||
void AddHeader(Ptr<Packet> p, Mac48Address dst, Mac48Address src, uint16_t ethertype, uint16_t vid, uint8_t pcp, uint8_t dei);
|
||||
|
||||
/**
|
||||
* Start Sending a Packet Down the Wire.
|
||||
*
|
||||
* The TransmitStart method is the method that is used internally in the
|
||||
* EthernetNetDevice to begin the process of sending a packet out on
|
||||
* the channel. The corresponding method is called on the channel to let
|
||||
* it know that the physical device this class represents has virtually
|
||||
* started sending signals. An event is scheduled for the time at which
|
||||
* the bits have been completely transmitted.
|
||||
*
|
||||
* \see EthernetChannel::TransmitStart ()
|
||||
* \see TransmitComplete()
|
||||
* \param p a reference to the packet to send
|
||||
* \returns true if success, false on failure
|
||||
*/
|
||||
bool TransmitStart(Ptr<Packet> p);
|
||||
|
||||
/**
|
||||
* Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
|
||||
*
|
||||
* The TransmitComplete method is used internally to finish the process
|
||||
* of sending a packet out on the channel.
|
||||
*/
|
||||
void TransmitComplete();
|
||||
|
||||
/**
|
||||
* Find the nextEligible Queue for transimission
|
||||
*
|
||||
* \returns Int id to the queue.
|
||||
*/
|
||||
virtual int TransmitSelection();
|
||||
|
||||
virtual void CheckForReadyPacket();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Make the link up and running
|
||||
*
|
||||
* It calls also the linkChange callback.
|
||||
*/
|
||||
void NotifyLinkUp();
|
||||
|
||||
/**
|
||||
* Enumeration of the states of the transmit machine of the net device.
|
||||
*/
|
||||
enum TxMachineState
|
||||
{
|
||||
READY, /**< The transmitter is ready to begin transmission of a packet */
|
||||
BUSY /**< The transmitter is busy transmitting a packet */
|
||||
};
|
||||
|
||||
/**
|
||||
* The state of the Net Device transmit state machine.
|
||||
*/
|
||||
TxMachineState m_txMachineState;
|
||||
|
||||
/**
|
||||
* The data rate that the Net Device uses to simulate packet transmission
|
||||
* timing.
|
||||
*/
|
||||
DataRate m_bps;
|
||||
|
||||
/**
|
||||
* The preamble and start of frame delimiter gap that the Net Device uses to throttle packet
|
||||
* transmission in bytes
|
||||
*/
|
||||
uint8_t m_preambleAndSFDGap;
|
||||
|
||||
/**
|
||||
* The interframe gap that the Net Device uses to throttle packet
|
||||
* transmission in bytes
|
||||
*/
|
||||
uint8_t m_interframeGap;
|
||||
|
||||
/**
|
||||
* The EthernetChannel to which this EthernetNetDevice has been
|
||||
* attached.
|
||||
*/
|
||||
Ptr<EthernetChannel> m_channel;
|
||||
|
||||
/**
|
||||
* The Queues which this EthernetNetDevice uses as a packet source.
|
||||
* Management of this Queues has been delegated to the EthernetNetDevice
|
||||
* and it has the responsibility for deletion.
|
||||
* \see class DropTailQueue
|
||||
*/
|
||||
std::vector<Ptr<Queue<Packet>>> m_queues;
|
||||
|
||||
/**
|
||||
* Error model for receive packet events
|
||||
*/
|
||||
Ptr<ErrorModel> m_receiveErrorModel;
|
||||
|
||||
/**
|
||||
* The trace source fired when packets come into the "top" of the device
|
||||
* at the L3/L2 transition, before being queued for transmission.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_macTxTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired when packets coming into the "top" of the device
|
||||
* at the L3/L2 transition are dropped before being queued for transmission.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_macTxDropTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired for packets successfully received by the device
|
||||
* immediately before being forwarded up to higher layers (at the L2/L3
|
||||
* transition). This is a promiscuous trace (which doesn't mean a lot here
|
||||
* in the point-to-point device).
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_macPromiscRxTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired for packets successfully received by the device
|
||||
* immediately before being forwarded up to higher layers (at the L2/L3
|
||||
* transition). This is a non-promiscuous trace (which doesn't mean a lot
|
||||
* here in the point-to-point device).
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_macRxTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired for packets successfully received by the device
|
||||
* but are dropped before being forwarded up to higher layers (at the L2/L3
|
||||
* transition).
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_macRxDropTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired when a packet begins the transmission process on
|
||||
* the medium.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_phyTxBeginTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired when a packet ends the transmission process on
|
||||
* the medium.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_phyTxEndTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired when the phy layer drops a packet before it tries
|
||||
* to transmit it.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_phyTxDropTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired when a packet begins the reception process from
|
||||
* the medium -- when the simulated first bit(s) arrive.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_phyRxBeginTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired when a packet ends the reception process from
|
||||
* the medium.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_phyRxEndTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired when the phy layer drops a packet it has received.
|
||||
* This happens if the receiver is not enabled or the error model is active
|
||||
* and indicates that the packet is corrupt.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_phyRxDropTrace;
|
||||
|
||||
/**
|
||||
* The trace source fired when the packet is receive to compute latency.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_latencyTrace;
|
||||
|
||||
/**
|
||||
* TracedCallback signature for packet transmission/reception events
|
||||
* (for external visualyzer).
|
||||
*
|
||||
* \param [in] packet The packet being transmitted.
|
||||
* \param [in] tx or rx NetDevice.
|
||||
*/
|
||||
typedef void (*MacTxAnimationCallback)(Ptr<const Packet> packet,
|
||||
Ptr<NetDevice> device);
|
||||
|
||||
TracedCallback<Ptr<const Packet>, Ptr<NetDevice>> m_macTxAnimationTrace;
|
||||
TracedCallback<Ptr<const Packet>, Ptr<NetDevice>> m_macRxAnimationTrace;
|
||||
/**
|
||||
* A trace source that emulates a non-promiscuous protocol sniffer connected
|
||||
* to the device. Unlike your average everyday sniffer, this trace source
|
||||
* will not fire on PACKET_OTHERHOST events.
|
||||
*
|
||||
* On the transmit size, this trace hook will fire after a packet is dequeued
|
||||
* from the device queue for transmission. In Linux, for example, this would
|
||||
* correspond to the point just before a device \c hard_start_xmit where
|
||||
* \c dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET
|
||||
* ETH_P_ALL handlers.
|
||||
*
|
||||
* On the receive side, this trace hook will fire when a packet is received,
|
||||
* just before the receive callback is executed. In Linux, for example,
|
||||
* this would correspond to the point at which the packet is dispatched to
|
||||
* packet sniffers in \c netif_receive_skb.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_snifferTrace;
|
||||
|
||||
/**
|
||||
* A trace source that emulates a promiscuous mode protocol sniffer connected
|
||||
* to the device. This trace source fire on packets destined for any host
|
||||
* just like your average everyday packet sniffer.
|
||||
*
|
||||
* On the transmit size, this trace hook will fire after a packet is dequeued
|
||||
* from the device queue for transmission. In Linux, for example, this would
|
||||
* correspond to the point just before a device \c hard_start_xmit where
|
||||
* \c dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET
|
||||
* ETH_P_ALL handlers.
|
||||
*
|
||||
* On the receive side, this trace hook will fire when a packet is received,
|
||||
* just before the receive callback is executed. In Linux, for example,
|
||||
* this would correspond to the point at which the packet is dispatched to
|
||||
* packet sniffers in \c netif_receive_skb.
|
||||
*/
|
||||
TracedCallback<Ptr<const Packet>> m_promiscSnifferTrace;
|
||||
|
||||
|
||||
TracedCallback<std::vector<Ptr<Queue<Packet>>>,
|
||||
bool,
|
||||
Ptr<const Packet>> m_FIFOStateSnifferTrace;
|
||||
|
||||
|
||||
Ptr<Node> m_node; //!< Node owning this NetDevice
|
||||
Mac48Address m_address; //!< Mac48Address of this NetDevice
|
||||
NetDevice::ReceiveCallback m_rxCallback; //!< Receive callback
|
||||
NetDevice::PromiscReceiveCallback m_promiscCallback; //!< Receive callback
|
||||
// (promisc data)
|
||||
uint32_t m_ifIndex; //!< Index of the interface
|
||||
bool m_linkUp; //!< Identify if the link is up or not
|
||||
TracedCallback<> m_linkChangeCallbacks; //!< Callback for the link change event
|
||||
|
||||
static const uint16_t DEFAULT_MTU = 1500; //!< Default MTU
|
||||
|
||||
/**
|
||||
* \brief The Maximum Transmission Unit
|
||||
*
|
||||
* This corresponds to the maximum
|
||||
* number of bytes that can be transmitted as seen from higher layers.
|
||||
* This corresponds to the 1500 byte MTU size often seen on IP over
|
||||
* Ethernet.
|
||||
*/
|
||||
uint32_t m_mtu;
|
||||
|
||||
Ptr<Packet> m_currentPkt; //!< Current packet processed
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ETHERNET_NET_DEVICE_H */
|
||||
77
contrib/ethernet/model/switch-channel.cc
Normal file
77
contrib/ethernet/model/switch-channel.cc
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "switch-channel.h"
|
||||
|
||||
#include "ns3/log.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \ingroup ethernet
|
||||
* ns3::SwitchChannel implementation.
|
||||
*/
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("SwitchChannel");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(SwitchChannel);
|
||||
|
||||
TypeId
|
||||
SwitchChannel::GetTypeId()
|
||||
{
|
||||
static TypeId tid = TypeId("ns3::SwitchChannel")
|
||||
.SetParent<Channel>()
|
||||
.SetGroupName("Ethernet")
|
||||
.AddConstructor<SwitchChannel>();
|
||||
return tid;
|
||||
}
|
||||
|
||||
SwitchChannel::SwitchChannel()
|
||||
: Channel()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
}
|
||||
|
||||
SwitchChannel::~SwitchChannel()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
|
||||
for (auto iter = m_switchedChannels.begin(); iter != m_switchedChannels.end(); iter++)
|
||||
{
|
||||
*iter = nullptr;
|
||||
}
|
||||
m_switchedChannels.clear();
|
||||
}
|
||||
|
||||
void
|
||||
SwitchChannel::AddChannel(Ptr<Channel> switchedChannel)
|
||||
{
|
||||
m_switchedChannels.push_back(switchedChannel);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
SwitchChannel::GetNDevices() const
|
||||
{
|
||||
uint32_t ndevices = 0;
|
||||
for (auto iter = m_switchedChannels.begin(); iter != m_switchedChannels.end(); iter++)
|
||||
{
|
||||
ndevices += (*iter)->GetNDevices();
|
||||
}
|
||||
return ndevices;
|
||||
}
|
||||
|
||||
Ptr<NetDevice>
|
||||
SwitchChannel::GetDevice(std::size_t i) const
|
||||
{
|
||||
std::size_t ndevices = 0;
|
||||
for (auto iter = m_switchedChannels.begin(); iter != m_switchedChannels.end(); iter++)
|
||||
{
|
||||
if ((i - ndevices) < (*iter)->GetNDevices())
|
||||
{
|
||||
return (*iter)->GetDevice(i - ndevices);
|
||||
}
|
||||
ndevices += (*iter)->GetNDevices();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
59
contrib/ethernet/model/switch-channel.h
Normal file
59
contrib/ethernet/model/switch-channel.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef SWITCH_CHANNEL_H
|
||||
#define SWITCH_CHANNEL_H
|
||||
|
||||
#include "ns3/channel.h"
|
||||
#include "ns3/net-device.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \ingroup ethernet
|
||||
* ns3::SwitchChannel declaration.
|
||||
*/
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
/**
|
||||
* \ingroup bridge
|
||||
*
|
||||
* \brief Virtual channel implementation for bridges (BridgeNetDevice).
|
||||
*
|
||||
* Just like SwitchNetDevice aggregates multiple NetDevices,
|
||||
* SwitchChannel aggregates multiple channels and make them appear as
|
||||
* a single channel to upper layers.
|
||||
* This class is greatly inspire form BridgeChannel
|
||||
*/
|
||||
class SwitchChannel : public Channel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId();
|
||||
SwitchChannel();
|
||||
~SwitchChannel() override;
|
||||
|
||||
// Delete copy constructor and assignment operator to avoid misuse
|
||||
SwitchChannel(const SwitchChannel&) = delete;
|
||||
SwitchChannel& operator=(const SwitchChannel&) = delete;
|
||||
|
||||
/**
|
||||
* Adds a channel to the bridged pool
|
||||
* \param bridgedChannel the channel to add to the pool
|
||||
*/
|
||||
void AddChannel(Ptr<Channel> bridgedChannel);
|
||||
|
||||
// virtual methods implementation, from Channel
|
||||
std::size_t GetNDevices() const override;
|
||||
Ptr<NetDevice> GetDevice(std::size_t i) const override;
|
||||
|
||||
private:
|
||||
std::vector<Ptr<Channel>> m_switchedChannels; //!< pool of switched channels
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* SWITCH_CHANNEL_H */
|
||||
427
contrib/ethernet/model/switch-net-device.cc
Normal file
427
contrib/ethernet/model/switch-net-device.cc
Normal file
@@ -0,0 +1,427 @@
|
||||
#include "switch-net-device.h"
|
||||
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/channel.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
|
||||
#include "ns3/ethernet-header2.h"
|
||||
#include "ns3/net-device.h"
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \ingroup ethernet
|
||||
* ns3::SwitchNetDevice implementation.
|
||||
*/
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("SwitchNetDevice");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(SwitchNetDevice);
|
||||
|
||||
TypeId
|
||||
SwitchNetDevice::GetTypeId()
|
||||
{
|
||||
static TypeId tid =
|
||||
TypeId("ns3::SwitchNetDevice")
|
||||
.SetParent<NetDevice>()
|
||||
.SetGroupName("Ethernet")
|
||||
.AddConstructor<SwitchNetDevice>()
|
||||
.AddAttribute("Mtu",
|
||||
"The MAC-level Maximum Transmission Unit",
|
||||
UintegerValue(1500),
|
||||
MakeUintegerAccessor(&SwitchNetDevice::SetMtu, &SwitchNetDevice::GetMtu),
|
||||
MakeUintegerChecker<uint16_t>())
|
||||
.AddAttribute("MinForwardingLatency",
|
||||
"The minimum latency experienced by the packet during forwarding",
|
||||
TimeValue(Seconds(0)),
|
||||
MakeTimeAccessor(&SwitchNetDevice::m_minForwardingLatency),
|
||||
MakeTimeChecker())
|
||||
.AddAttribute("MaxForwardingLatency",
|
||||
"The maximun latency experienced by the packet during forwarding",
|
||||
TimeValue(Seconds(0)),
|
||||
MakeTimeAccessor(&SwitchNetDevice::m_maxForwardingLatency),
|
||||
MakeTimeChecker())
|
||||
.AddAttribute("MaxPortNumber",
|
||||
"The maximum number of port",
|
||||
UintegerValue(65535),
|
||||
MakeUintegerAccessor(&SwitchNetDevice::m_maxPortNumber),
|
||||
MakeUintegerChecker<uint16_t>())
|
||||
.AddAttribute("MaxFdbEntryNumber",
|
||||
"The maximum number of entry in the forwarding database",
|
||||
UintegerValue(65535),
|
||||
MakeUintegerAccessor(&SwitchNetDevice::m_maxFdbEntryNumber),
|
||||
MakeUintegerChecker<uint16_t>());
|
||||
return tid;
|
||||
}
|
||||
|
||||
SwitchNetDevice::SwitchNetDevice()
|
||||
: m_node(nullptr),
|
||||
m_ifIndex(0)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
m_channel = CreateObject<SwitchChannel>();
|
||||
}
|
||||
|
||||
SwitchNetDevice::~SwitchNetDevice()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::DoDispose()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
for (auto iter = m_ports.begin(); iter != m_ports.end(); iter++)
|
||||
{
|
||||
*iter = nullptr;
|
||||
}
|
||||
m_ports.clear();
|
||||
m_forwardingTable.clear();
|
||||
m_channel = nullptr;
|
||||
m_node = nullptr;
|
||||
NetDevice::DoDispose();
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::ReceiveFromDevice(Ptr<NetDevice> incomingPort,
|
||||
Ptr<const Packet> packet,
|
||||
uint16_t protocol,
|
||||
const Address& src,
|
||||
const Address& dst,
|
||||
PacketType packetType)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
NS_LOG_DEBUG("UID is " << packet->GetUid());
|
||||
|
||||
Mac48Address src48 = Mac48Address::ConvertFrom(src);
|
||||
Mac48Address dst48 = Mac48Address::ConvertFrom(dst);
|
||||
|
||||
if (!m_promiscRxCallback.IsNull())
|
||||
{
|
||||
m_promiscRxCallback(this, packet, protocol, src, dst, packetType);
|
||||
}
|
||||
switch (packetType)
|
||||
{
|
||||
case PACKET_HOST:
|
||||
if (dst48 == m_address)
|
||||
{
|
||||
m_rxCallback(this, packet, protocol, src);
|
||||
}
|
||||
break;
|
||||
case PACKET_MULTICAST:
|
||||
case PACKET_BROADCAST:
|
||||
m_rxCallback(this, packet, protocol, src);
|
||||
ForwardBroadcast(incomingPort, packet, protocol, src48, dst48);
|
||||
break;
|
||||
|
||||
case PACKET_OTHERHOST:
|
||||
if (dst48 == m_address)
|
||||
{
|
||||
m_rxCallback(this, packet, protocol, src);
|
||||
}
|
||||
else
|
||||
{
|
||||
Forward(incomingPort, packet, protocol, src48, dst48);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::Forward(Ptr<NetDevice> incomingPort,
|
||||
Ptr<const Packet> packet,
|
||||
uint16_t protocol,
|
||||
Mac48Address src,
|
||||
Mac48Address dst)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
Ptr<Packet> originalPacket = packet->Copy();
|
||||
EthernetHeader2 header;
|
||||
originalPacket->RemoveHeader(header);
|
||||
uint16_t vid = header.GetVid();
|
||||
//NS_LOG_INFO(Names::FindName(this) << " Look in forwarding table for Pkt #" << packet->GetUid());
|
||||
std::vector<Ptr<NetDevice>> outPorts = GetOutputPortsFromForwardingTable(dst, vid);
|
||||
EventId e;
|
||||
int s = outPorts.size();
|
||||
for(int i=0; i < s; i++){
|
||||
//Avoid sending on the incomingPort
|
||||
if(outPorts[i] != incomingPort){
|
||||
Ptr<UniformRandomVariable> randVar = CreateObject<UniformRandomVariable>();
|
||||
Time forwardingLatency = NanoSeconds(randVar->GetValue(m_minForwardingLatency.GetNanoSeconds(), m_maxForwardingLatency.GetNanoSeconds()));
|
||||
Simulator::Schedule(forwardingLatency, &NetDevice::SendFrom, outPorts[i], packet->Copy(), src, dst, protocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::ForwardBroadcast(Ptr<NetDevice> incomingPort,
|
||||
Ptr<const Packet> packet,
|
||||
uint16_t protocol,
|
||||
Mac48Address src,
|
||||
Mac48Address dst)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
|
||||
Forward(incomingPort, packet, protocol, src, dst);
|
||||
}
|
||||
|
||||
std::vector<Ptr<NetDevice>>
|
||||
SwitchNetDevice::GetOutputPortsFromForwardingTable(Mac48Address dest, uint16_t vid)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
int s = m_forwardingTable.size();
|
||||
for(int i=0; i < s; i++){
|
||||
if(m_forwardingTable[i].dest == dest and m_forwardingTable[i].vid==vid){
|
||||
// NS_LOG_INFO(Names::FindName(this) << " Forwarding Table : Match on vid "<< vid << " for " << m_forwardingTable[i].associatedPorts.size() << " output port(s) ");
|
||||
return m_forwardingTable[i].associatedPorts;
|
||||
}
|
||||
}
|
||||
// NS_LOG_INFO(Names::FindName(this) << " Forwarding Table : No Match on vid "<< vid);
|
||||
return {};
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::AddForwardingTableEntry(Mac48Address dest, uint16_t vid, std::vector<Ptr<NetDevice>> outPorts)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
NS_ASSERT_MSG(m_forwardingTable.size() < m_maxFdbEntryNumber, "Trying to add more forwarding database entry than the " << m_maxFdbEntryNumber << " available.");
|
||||
PortsToVidAssociation entry = {dest, vid, outPorts};
|
||||
m_forwardingTable.insert(m_forwardingTable.end(), entry);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SwitchNetDevice::GetNSwitchPorts() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return m_ports.size();
|
||||
}
|
||||
|
||||
Ptr<NetDevice>
|
||||
SwitchNetDevice::GetSwitchPort(uint32_t n) const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return m_ports[n];
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::AddSwitchPort(Ptr<NetDevice> switchPort)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
NS_ASSERT_MSG(m_ports.size() < m_maxPortNumber, "Trying to add more switch port than the " << m_maxPortNumber << " available.");
|
||||
//NS_ASSERT(switchPort != this);
|
||||
if (!Mac48Address::IsMatchingType(switchPort->GetAddress()))
|
||||
{
|
||||
NS_FATAL_ERROR("Device does not support eui 48 addresses: cannot be added to switch.");
|
||||
}
|
||||
if (!switchPort->SupportsSendFrom())
|
||||
{
|
||||
NS_FATAL_ERROR("Device does not support SendFrom: cannot be added to switch.");
|
||||
}
|
||||
if (m_address == Mac48Address())
|
||||
{
|
||||
m_address = Mac48Address::ConvertFrom(switchPort->GetAddress());
|
||||
}
|
||||
|
||||
NS_LOG_DEBUG("RegisterProtocolHandler for " << switchPort->GetInstanceTypeId().GetName());
|
||||
m_node->RegisterProtocolHandler(MakeCallback(&SwitchNetDevice::ReceiveFromDevice, this),
|
||||
0,
|
||||
switchPort,
|
||||
true);
|
||||
m_ports.push_back(switchPort);
|
||||
m_channel->AddChannel(switchPort->GetChannel());
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::SetIfIndex(const uint32_t index)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
m_ifIndex = index;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SwitchNetDevice::GetIfIndex() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return m_ifIndex;
|
||||
}
|
||||
|
||||
Ptr<Channel>
|
||||
SwitchNetDevice::GetChannel() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::SetAddress(Address address)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
m_address = Mac48Address::ConvertFrom(address);
|
||||
}
|
||||
|
||||
Address
|
||||
SwitchNetDevice::GetAddress() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return m_address;
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::SetMtu(const uint16_t mtu)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
m_mtu = mtu;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
SwitchNetDevice::GetMtu() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return m_mtu;
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::IsLinkUp() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::AddLinkChangeCallback(Callback<void> callback)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::IsBroadcast() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
SwitchNetDevice::GetBroadcast() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return Mac48Address("ff:ff:ff:ff:ff:ff");
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::IsMulticast() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
SwitchNetDevice::GetMulticast(Ipv4Address multicastGroup) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this << multicastGroup);
|
||||
Mac48Address multicast = Mac48Address::GetMulticast(multicastGroup);
|
||||
return multicast;
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::IsPointToPoint() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::IsBridge() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return SendFrom(packet, m_address, dest, protocolNumber);
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::SendFrom(Ptr<Packet> packet,
|
||||
const Address& source,
|
||||
const Address& dest,
|
||||
uint16_t protocolNumber)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
Mac48Address src = Mac48Address::ConvertFrom(source);
|
||||
Mac48Address dst = Mac48Address::ConvertFrom(dest);
|
||||
|
||||
|
||||
Ptr<Packet> originalPacket = packet->Copy();
|
||||
EthernetHeader2 header;
|
||||
originalPacket->RemoveHeader(header);
|
||||
uint16_t vid = header.GetVid();
|
||||
|
||||
std::vector<Ptr<NetDevice>> outPorts = GetOutputPortsFromForwardingTable(dst, vid);
|
||||
int s = outPorts.size();
|
||||
for(int i=0; i < s; i++){
|
||||
outPorts[i]->SendFrom(packet->Copy(), src, dst, protocolNumber);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Ptr<Node>
|
||||
SwitchNetDevice::GetNode() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return m_node;
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::SetNode(Ptr<Node> node)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
m_node = node;
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::NeedsArp() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
m_rxCallback = cb;
|
||||
}
|
||||
|
||||
void
|
||||
SwitchNetDevice::SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
m_promiscRxCallback = cb;
|
||||
}
|
||||
|
||||
bool
|
||||
SwitchNetDevice::SupportsSendFrom() const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
SwitchNetDevice::GetMulticast(Ipv6Address addr) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this << addr);
|
||||
return Mac48Address::GetMulticast(addr);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
220
contrib/ethernet/model/switch-net-device.h
Normal file
220
contrib/ethernet/model/switch-net-device.h
Normal file
@@ -0,0 +1,220 @@
|
||||
#ifndef SWITCH_NET_DEVICE_H
|
||||
#define SWITCH_NET_DEVICE_H
|
||||
|
||||
#include "switch-channel.h"
|
||||
|
||||
#include "ns3/net-device.h"
|
||||
#include "ns3/mac48-address.h"
|
||||
#include "ns3/net-device.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \ingroup ethernet
|
||||
* ns3::SwitchNetDevice declaration.
|
||||
*/
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
class Node;
|
||||
|
||||
/**
|
||||
* \brief a virtual net device that bridges multiple LAN segments
|
||||
*
|
||||
* The SwitchNetDevice object is a "virtual" netdevice that aggregates
|
||||
* multiple "real" netdevices and implements the data plane forwarding
|
||||
* part of IEEE 802.1D. By adding a SwitchNetDevice to a Node, it
|
||||
* will act as a "switch" to multiple LAN segments.
|
||||
*
|
||||
* \attention The switch netdevice don't implement a "Learning bridge" algorithm
|
||||
* or Spanning Tree Protocol as described in 802.1D
|
||||
*
|
||||
* \attention Switching is designed to work only with Ethernet NetDevices
|
||||
* modelling IEEE 802-style technologies, such as EthernetNetDevice
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup ethernet
|
||||
* \brief a virtual net device that bridges multiple LAN segments
|
||||
*/
|
||||
class SwitchNetDevice : public NetDevice
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId();
|
||||
SwitchNetDevice();
|
||||
~SwitchNetDevice() override;
|
||||
|
||||
// Delete copy constructor and assignment operator to avoid misuse
|
||||
SwitchNetDevice(const SwitchNetDevice&) = delete;
|
||||
SwitchNetDevice& operator=(const SwitchNetDevice&) = delete;
|
||||
|
||||
/**
|
||||
* \brief Add a 'port' to a switch device
|
||||
* \param switchPort the NetDevice to add
|
||||
*
|
||||
* This method adds a new switch port to a SwitchNetDevice, so that
|
||||
* the new switch port NetDevice becomes part of the switch and L2
|
||||
* frames start being forwarded to/from this NetDevice.
|
||||
*
|
||||
* \attention The netdevice that is being added as switch port must
|
||||
* _not_ have an IP address. In order to add IP connectivity to a
|
||||
* bridging node you must enable IP on the SwitchNetDevice itself,
|
||||
* never on its port netdevices.
|
||||
*/
|
||||
void AddSwitchPort(Ptr<NetDevice> switchPort);
|
||||
|
||||
/**
|
||||
* \brief Gets the number of switched 'ports', i.e., the NetDevices currently switched.
|
||||
*
|
||||
* \return the number of switched ports.
|
||||
*/
|
||||
uint32_t GetNSwitchPorts() const;
|
||||
|
||||
/**
|
||||
* \brief Gets the n-th switched port.
|
||||
* \param n the port index
|
||||
* \return the n-th switched NetDevice
|
||||
*/
|
||||
Ptr<NetDevice> GetSwitchPort(uint32_t n) const;
|
||||
|
||||
// inherited from NetDevice base class.
|
||||
void SetIfIndex(const uint32_t index) override;
|
||||
uint32_t GetIfIndex() const override;
|
||||
Ptr<Channel> 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<void> 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> packet, const Address& dest, uint16_t protocolNumber) override;
|
||||
bool SendFrom(Ptr<Packet> packet,
|
||||
const Address& source,
|
||||
const Address& dest,
|
||||
uint16_t protocolNumber) override;
|
||||
Ptr<Node> GetNode() const override;
|
||||
void SetNode(Ptr<Node> node) override;
|
||||
bool NeedsArp() const override;
|
||||
void SetReceiveCallback(NetDevice::ReceiveCallback cb) override;
|
||||
void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb) override;
|
||||
bool SupportsSendFrom() const override;
|
||||
Address GetMulticast(Ipv6Address addr) const override;
|
||||
|
||||
/**
|
||||
* \brief Add a entry to the forwarding table
|
||||
* \param dest destination mac
|
||||
* \param vid Vlan ID
|
||||
* \param outPorts vector of output port
|
||||
*/
|
||||
void AddForwardingTableEntry(Mac48Address dest,
|
||||
uint16_t vid,
|
||||
std::vector<Ptr<NetDevice>> outPorts);
|
||||
protected:
|
||||
void DoDispose() override;
|
||||
|
||||
/**
|
||||
* \brief Receives a packet from one switched port.
|
||||
* \param device the originating port
|
||||
* \param packet the received packet
|
||||
* \param protocol the packet protocol (e.g., Ethertype)
|
||||
* \param source the packet source
|
||||
* \param destination the packet destination
|
||||
* \param packetType the packet type (e.g., host, broadcast, etc.)
|
||||
*/
|
||||
void ReceiveFromDevice(Ptr<NetDevice> device,
|
||||
Ptr<const Packet> packet,
|
||||
uint16_t protocol,
|
||||
const Address& source,
|
||||
const Address& destination,
|
||||
PacketType packetType);
|
||||
|
||||
/**
|
||||
* \brief Forwards a packet
|
||||
* \param incomingPort the packet incoming port
|
||||
* \param packet the packet
|
||||
* \param protocol the packet protocol (e.g., Ethertype)
|
||||
* \param src the packet source
|
||||
* \param dst the packet destination
|
||||
*/
|
||||
void Forward(Ptr<NetDevice> incomingPort,
|
||||
Ptr<const Packet> packet,
|
||||
uint16_t protocol,
|
||||
Mac48Address src,
|
||||
Mac48Address dst);
|
||||
|
||||
/**
|
||||
* \brief Forwards a broadcast or a multicast packet
|
||||
* \param incomingPort the packet incoming port
|
||||
* \param packet the packet
|
||||
* \param protocol the packet protocol (e.g., Ethertype)
|
||||
* \param src the packet source
|
||||
* \param dst the packet destination
|
||||
*/
|
||||
void ForwardBroadcast(Ptr<NetDevice> incomingPort,
|
||||
Ptr<const Packet> packet,
|
||||
uint16_t protocol,
|
||||
Mac48Address src,
|
||||
Mac48Address dst);
|
||||
|
||||
/**
|
||||
* \brief Get the output ports from the forwarding table
|
||||
* \param dest destination mac
|
||||
* \param vid Vlan ID
|
||||
* \return output ports
|
||||
*/
|
||||
std::vector<Ptr<NetDevice>> GetOutputPortsFromForwardingTable(Mac48Address dest,
|
||||
uint16_t vid);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
NetDevice::ReceiveCallback m_rxCallback; //!< receive callback
|
||||
NetDevice::PromiscReceiveCallback m_promiscRxCallback; //!< promiscuous receive callback
|
||||
|
||||
Mac48Address m_address; //!< MAC address of the NetDevice
|
||||
|
||||
/**
|
||||
* \ingroup ethernet
|
||||
* Structure holding the association between ports and vid for a mac destination address
|
||||
*/
|
||||
struct PortsToVidAssociation
|
||||
{
|
||||
Mac48Address dest;
|
||||
uint16_t vid;
|
||||
std::vector<Ptr<NetDevice>> associatedPorts;
|
||||
};
|
||||
|
||||
std::vector<PortsToVidAssociation> m_forwardingTable; //!< Container for forwarding table
|
||||
Ptr<Node> m_node; //!< node owning this NetDevice
|
||||
Ptr<SwitchChannel> m_channel; //!< virtual bridged channel
|
||||
std::vector<Ptr<NetDevice>> m_ports; //!< switched ports
|
||||
uint32_t m_ifIndex; //!< Interface index
|
||||
uint16_t m_mtu; //!< MTU of the switched NetDevice
|
||||
|
||||
Time m_minForwardingLatency;
|
||||
Time m_maxForwardingLatency;
|
||||
|
||||
uint16_t m_maxPortNumber;
|
||||
uint16_t m_maxFdbEntryNumber;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* SWITCH_NET_DEVICE_H */
|
||||
1036
contrib/ethernet/test/ethernet-test-suite.cc
Normal file
1036
contrib/ethernet/test/ethernet-test-suite.cc
Normal file
File diff suppressed because it is too large
Load Diff
26
contrib/ethernet/test/examples-to-run.py
Normal file
26
contrib/ethernet/test/examples-to-run.py
Normal file
@@ -0,0 +1,26 @@
|
||||
#! /usr/bin/env python3
|
||||
|
||||
# A list of C++ examples to run in order to ensure that they remain
|
||||
# buildable and runnable over time. Each tuple in the list contains
|
||||
#
|
||||
# (example_name, do_run, do_valgrind_run).
|
||||
#
|
||||
# See test.py for more information.
|
||||
cpp_examples = [
|
||||
("ethernet-point2point", "True", "True"),
|
||||
("ethernet-point2point-withPropagationDelay", "True", "True"),
|
||||
("ethernet-point2point-withSmallFifo", "True", "True"),
|
||||
("ethernet-point2point-10Gb", "True", "True"),
|
||||
("ethernet-switched", "True", "True"),
|
||||
("ethernet-switched-withLatencyCallback", "True", "True"),
|
||||
("ethernet-switched-withPcap", "True", "True"),
|
||||
("ethernet-switched-withRxTxCallback", "True", "True"),
|
||||
]
|
||||
|
||||
# A list of Python examples to run in order to ensure that they remain
|
||||
# runnable over time. Each tuple in the list contains
|
||||
#
|
||||
# (example_name, do_run).
|
||||
#
|
||||
# See test.py for more information.
|
||||
python_examples = []
|
||||
Reference in New Issue
Block a user