280 lines
11 KiB
C++
280 lines
11 KiB
C++
|
|
// Include a header file from your module to test.
|
||
|
|
#include "ns3/tsn-net-device.h"
|
||
|
|
#include "ns3/ethernet-channel.h"
|
||
|
|
#include "ns3/ethernet-header2.h"
|
||
|
|
#include "ns3/ethernet-generator.h"
|
||
|
|
#include "ns3/switch-net-device.h"
|
||
|
|
#include "ns3/stream-identification-function-null.h"
|
||
|
|
|
||
|
|
// An essential include is test.h
|
||
|
|
#include "ns3/test.h"
|
||
|
|
#include "ns3/core-module.h"
|
||
|
|
#include "ns3/drop-tail-queue.h"
|
||
|
|
#include "ns3/timestamp-tag.h"
|
||
|
|
|
||
|
|
// Do not put your test classes in namespace ns3. You may find it useful
|
||
|
|
// to use the using directive to access the ns3 namespace directly
|
||
|
|
using namespace ns3;
|
||
|
|
NS_LOG_COMPONENT_DEFINE("PsfpTestSuite");
|
||
|
|
// Add a doxygen group for tests.
|
||
|
|
// If you have more than one test, this should be in only one of them.
|
||
|
|
/**
|
||
|
|
* \defgroup Psfp-tests Tests for Psfp
|
||
|
|
* \ingroup tsn
|
||
|
|
* \ingroup tests
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* \ingroup Psfp-tests
|
||
|
|
* Check if message crossed a point to point tsn channel
|
||
|
|
*/
|
||
|
|
class PsfpBasicTestCase : public TestCase
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
PsfpBasicTestCase(
|
||
|
|
uint64_t receivedExpected,
|
||
|
|
uint16_t streamHandle,
|
||
|
|
uint8_t priority,
|
||
|
|
uint16_t maxSDUSize,
|
||
|
|
bool streamBlockedDueToOversizeFrameEnable,
|
||
|
|
DataRate cir,
|
||
|
|
uint16_t cbs,
|
||
|
|
DataRate eir,
|
||
|
|
uint16_t ebs,
|
||
|
|
bool dropOnYellow,
|
||
|
|
bool cf,
|
||
|
|
bool markAllFramesRedEnable);
|
||
|
|
virtual ~PsfpBasicTestCase();
|
||
|
|
|
||
|
|
private:
|
||
|
|
void DoRun() override;
|
||
|
|
void SendTx(Ptr<const Packet> p);
|
||
|
|
void ReceiveRx(Ptr<const Packet> p);
|
||
|
|
uint64_t m_sent{0}; //!< number of bytes sent
|
||
|
|
uint64_t m_received{0}; //!< number of bytes received
|
||
|
|
uint64_t m_received_expected;
|
||
|
|
uint16_t m_streamHandle;
|
||
|
|
uint8_t m_priority;
|
||
|
|
uint16_t m_maxSDUSize;
|
||
|
|
bool m_streamBlockedDueToOversizeFrameEnable;
|
||
|
|
DataRate m_cir;
|
||
|
|
uint16_t m_cbs;
|
||
|
|
DataRate m_eir;
|
||
|
|
uint16_t m_ebs;
|
||
|
|
bool m_dropOnYellow;
|
||
|
|
bool m_cf;
|
||
|
|
bool m_markAllFramesRedEnable;
|
||
|
|
};
|
||
|
|
|
||
|
|
// Add some help text to this case to describe what it is intended to test
|
||
|
|
PsfpBasicTestCase::PsfpBasicTestCase(
|
||
|
|
uint64_t receivedExpected,
|
||
|
|
uint16_t streamHandle,
|
||
|
|
uint8_t priority,
|
||
|
|
uint16_t maxSDUSize,
|
||
|
|
bool streamBlockedDueToOversizeFrameEnable,
|
||
|
|
DataRate cir,
|
||
|
|
uint16_t cbs,
|
||
|
|
DataRate eir,
|
||
|
|
uint16_t ebs,
|
||
|
|
bool dropOnYellow,
|
||
|
|
bool cf,
|
||
|
|
bool markAllFramesRedEnable)
|
||
|
|
: TestCase("Check if paquets cross a point to point ethernet channel, tsn net device and PSFP")
|
||
|
|
{
|
||
|
|
m_received_expected = receivedExpected;
|
||
|
|
m_streamHandle = streamHandle;
|
||
|
|
m_priority = priority;
|
||
|
|
m_maxSDUSize = maxSDUSize;
|
||
|
|
m_streamBlockedDueToOversizeFrameEnable = streamBlockedDueToOversizeFrameEnable;
|
||
|
|
m_cir = cir;
|
||
|
|
m_cbs = cbs;
|
||
|
|
m_eir = eir;
|
||
|
|
m_ebs = ebs;
|
||
|
|
m_dropOnYellow = dropOnYellow;
|
||
|
|
m_cf = cf;
|
||
|
|
m_markAllFramesRedEnable = markAllFramesRedEnable;
|
||
|
|
}
|
||
|
|
|
||
|
|
// This destructor does nothing but we include it as a reminder that
|
||
|
|
// the test case should clean up after itself
|
||
|
|
PsfpBasicTestCase::~PsfpBasicTestCase()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
PsfpBasicTestCase::SendTx(Ptr<const Packet> p)
|
||
|
|
{
|
||
|
|
m_sent += p->GetSize();
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
PsfpBasicTestCase::ReceiveRx(Ptr<const Packet> p)
|
||
|
|
{
|
||
|
|
m_received += p->GetSize();
|
||
|
|
}
|
||
|
|
|
||
|
|
//
|
||
|
|
// This method is the pure virtual method from class TestCase that every
|
||
|
|
// TestCase must implement
|
||
|
|
//
|
||
|
|
void
|
||
|
|
PsfpBasicTestCase::DoRun()
|
||
|
|
{
|
||
|
|
//Create two nodes
|
||
|
|
Ptr<TsnNode> n0 = CreateObject<TsnNode>();
|
||
|
|
Ptr<TsnNode> n1 = CreateObject<TsnNode>();
|
||
|
|
|
||
|
|
//Create and add a netDevice to each node
|
||
|
|
Ptr<TsnNetDevice> net0 = CreateObject<TsnNetDevice>();
|
||
|
|
n0->AddDevice(net0);
|
||
|
|
Ptr<TsnNetDevice> net1 = CreateObject<TsnNetDevice>();
|
||
|
|
n1->AddDevice(net1);
|
||
|
|
|
||
|
|
//Create a Tsn 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());
|
||
|
|
|
||
|
|
//Create and add FIFOs
|
||
|
|
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||
|
|
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||
|
|
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||
|
|
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||
|
|
|
||
|
|
//Stream identification
|
||
|
|
Ptr<NullStreamIdentificationFunction> sif0 = CreateObject<NullStreamIdentificationFunction>();
|
||
|
|
uint16_t StreamHandle = 10;
|
||
|
|
sif0->SetAttribute("VlanID", UintegerValue(1));
|
||
|
|
sif0->SetAttribute("Address", AddressValue(Mac48Address("ff:ff:ff:ff:ff:ff")));
|
||
|
|
n1->AddStreamIdentificationFunction(StreamHandle, sif0, {net1}, {}, {}, {});
|
||
|
|
|
||
|
|
//PSFP configuration - Stream Filter
|
||
|
|
Ptr<StreamFilterInstance> sfi0 = CreateObject<StreamFilterInstance>();
|
||
|
|
sfi0->SetAttribute("StreamHandle", IntegerValue(m_streamHandle));
|
||
|
|
sfi0->SetAttribute("Priority", IntegerValue(m_priority));
|
||
|
|
sfi0->SetAttribute("MaxSDUSize", UintegerValue(m_maxSDUSize));
|
||
|
|
sfi0->SetAttribute("StreamBlockedDueToOversizeFrameEnable", BooleanValue(m_streamBlockedDueToOversizeFrameEnable));
|
||
|
|
n1->AddStreamFilter(sfi0);
|
||
|
|
|
||
|
|
//PSFP configuration - Flow meter
|
||
|
|
Ptr<FlowMeterInstance> fm0 = CreateObject<FlowMeterInstance>();
|
||
|
|
fm0->SetAttribute("CIR", DataRateValue(m_cir));
|
||
|
|
fm0->SetAttribute("CBS", UintegerValue(m_cbs));
|
||
|
|
fm0->SetAttribute("EIR", DataRateValue(m_eir));
|
||
|
|
fm0->SetAttribute("EBS", UintegerValue(m_ebs));
|
||
|
|
fm0->SetAttribute("DropOnYellow", BooleanValue(m_dropOnYellow));
|
||
|
|
fm0->SetAttribute("CF", BooleanValue(m_cf));
|
||
|
|
fm0->SetAttribute("MarkAllFramesRedEnable", BooleanValue(m_markAllFramesRedEnable));
|
||
|
|
uint16_t fmid = n1->AddFlowMeter(fm0);
|
||
|
|
sfi0->AddFlowMeterInstanceId(fmid);
|
||
|
|
|
||
|
|
//Application description
|
||
|
|
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||
|
|
app0->Setup(net0);
|
||
|
|
app0->SetAttribute("BurstSize", UintegerValue(5));
|
||
|
|
app0->SetAttribute("PayloadSize", UintegerValue(1000));
|
||
|
|
app0->SetAttribute("Period", TimeValue(Seconds(5)));
|
||
|
|
app0->SetAttribute("VlanID", UintegerValue(1));
|
||
|
|
app0->SetAttribute("PCP", UintegerValue(0));
|
||
|
|
n0->AddApplication(app0);
|
||
|
|
app0->SetStartTime(Seconds(1));
|
||
|
|
app0->SetStopTime(Seconds(11));
|
||
|
|
|
||
|
|
Ptr<EthernetGenerator> app1 = CreateObject<EthernetGenerator>();
|
||
|
|
app1->Setup(net0);
|
||
|
|
app1->SetAttribute("BurstSize", UintegerValue(5));
|
||
|
|
app1->SetAttribute("PayloadSize", UintegerValue(1400));
|
||
|
|
app1->SetAttribute("Period", TimeValue(Seconds(5)));
|
||
|
|
app1->SetAttribute("VlanID", UintegerValue(1));
|
||
|
|
app1->SetAttribute("PCP", UintegerValue(0));
|
||
|
|
n0->AddApplication(app1);
|
||
|
|
app1->SetStartTime(Seconds(1.1));
|
||
|
|
app1->SetStopTime(Seconds(11.1));
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
//Callback to trace the message being send and received
|
||
|
|
net0->TraceConnectWithoutContext("MacTx",
|
||
|
|
MakeCallback(&PsfpBasicTestCase::SendTx, this));
|
||
|
|
net1->TraceConnectWithoutContext("MacRx",
|
||
|
|
MakeCallback(&PsfpBasicTestCase::ReceiveRx, this));
|
||
|
|
|
||
|
|
//Execute the simulation
|
||
|
|
Simulator::Stop(Seconds(14));
|
||
|
|
Simulator::Run();
|
||
|
|
Simulator::Destroy();
|
||
|
|
|
||
|
|
NS_TEST_ASSERT_MSG_EQ(m_sent, 2 * (5 * (1400 + 22) + 5 * (1000 + 22)), "10 Packets have been sent two times");
|
||
|
|
NS_TEST_ASSERT_MSG_EQ(m_received, m_received_expected, "All Packets sent have been received");
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
// The TestSuite class names the TestSuite, identifies what type of TestSuite,
|
||
|
|
// and enables the TestCases to be run. Typically, only the constructor for
|
||
|
|
// this class must be defined
|
||
|
|
|
||
|
|
/**
|
||
|
|
* \ingroup psfp-tests
|
||
|
|
* TestSuite for module psfp
|
||
|
|
*/
|
||
|
|
class PsfpTestSuite : public TestSuite
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
PsfpTestSuite();
|
||
|
|
};
|
||
|
|
|
||
|
|
PsfpTestSuite::PsfpTestSuite()
|
||
|
|
: TestSuite("psfp", UNIT)
|
||
|
|
{
|
||
|
|
LogComponentEnable("PsfpTestSuite", LOG_LEVEL_ALL);
|
||
|
|
//Point to point network with psfp
|
||
|
|
// Stream filter test
|
||
|
|
// All packet should pass because PSFP is well configured
|
||
|
|
AddTestCase(new PsfpBasicTestCase(2 * (5 * (1400 + 22) + 5 *(1000 + 22)), 10, 0, 1422, false, DataRate("1Gb/s"), 65535, DataRate("1Gb/s"), 65535, false, false, false), TestCase::QUICK);
|
||
|
|
// No packet should pass due to maxSDUSize filter
|
||
|
|
AddTestCase(new PsfpBasicTestCase(0, 10, 0, 1021, false, DataRate("1Gb/s"), 65535, DataRate("1Gb/s"), 65535, false, false, false), TestCase::QUICK);
|
||
|
|
// All packet should pass because the priority spec is wrong
|
||
|
|
AddTestCase(new PsfpBasicTestCase(2 * (5 * (1400 + 22) + 5 *(1000 + 22)), 10, 1, 1021, false, DataRate("1Gb/s"), 65535, DataRate("1Gb/s"), 65535, false, false, false), TestCase::QUICK);
|
||
|
|
// All packet should pass because the stream handle spec is wrong
|
||
|
|
AddTestCase(new PsfpBasicTestCase(2 * (5 * (1400 + 22) + 5 *(1000 + 22)), 11, 0, 1021, false, DataRate("1Gb/s"), 65535, DataRate("1Gb/s"), 65535, false, false, false), TestCase::QUICK);
|
||
|
|
// Only 2*5 packets of 1022octet packet should pass due to maxSDUSize filter
|
||
|
|
AddTestCase(new PsfpBasicTestCase(2 * (5 *(1000 + 22)),10 ,0 , 1022, false, DataRate("1Gb/s"), 65535, DataRate("1Gb/s"), 65535, false, false, false), TestCase::QUICK);
|
||
|
|
// Only 5 packets of 1022octet packet should pass due to maxSDUSize filter with m_streamBlockedDueToOversizeFrameEnable=true
|
||
|
|
AddTestCase(new PsfpBasicTestCase((5 *(1000 + 22)),10 ,0 , 1022, true, DataRate("1Gb/s"), 65535, DataRate("1Gb/s"), 65535, false, false, false), TestCase::QUICK);
|
||
|
|
|
||
|
|
// Flow meter test
|
||
|
|
//Two packets of 1022octet should pass in green
|
||
|
|
AddTestCase(new PsfpBasicTestCase(2 * (1000 + 22), 10 ,0 , 1422, false, DataRate("8000b/s"), 1022, DataRate("0Gb/s"), 0, false, false, false), TestCase::QUICK);
|
||
|
|
//One packets of 1022octet should pass in green
|
||
|
|
AddTestCase(new PsfpBasicTestCase(1 * (1000 + 22), 10 ,0 , 1422, false, DataRate("7999b/s"), 1022, DataRate("0Gb/s"), 0, false, false, false), TestCase::QUICK);
|
||
|
|
//Six packets of 1022octet should pass in green
|
||
|
|
AddTestCase(new PsfpBasicTestCase(6 * (1000 + 22), 10 ,0 , 1422, false, DataRate("8000b/s"), 65535, DataRate("0Gb/s"), 0, false, false, false), TestCase::QUICK);
|
||
|
|
//One packets of 1022octet should pass in green and the rest are drop due to MarkAllFramesRedEnable
|
||
|
|
AddTestCase(new PsfpBasicTestCase(1000 + 22, 10 ,0 , 1422, false, DataRate("8000b/s"), 65535, DataRate("0Gb/s"), 0, false, false, true), TestCase::QUICK);
|
||
|
|
// All packet should pass in yellow
|
||
|
|
AddTestCase(new PsfpBasicTestCase(2 * (5 * (1400 + 22) + 5 *(1000 + 22)),10 ,0 , 1422, false, DataRate("0Gb/s"), 0, DataRate("1Gb/s"), 65535, false, false, false), TestCase::QUICK);
|
||
|
|
// All packet should pass in yellow due to compling flag
|
||
|
|
AddTestCase(new PsfpBasicTestCase(2 * (5 * (1400 + 22) + 5 *(1000 + 22)),10 ,0 , 1422, false, DataRate("1Gb/s"), 999, DataRate("0Gb/s"), 65535, false, true, false), TestCase::QUICK);
|
||
|
|
// All packet should not pass due to dropOnYellow=true
|
||
|
|
AddTestCase(new PsfpBasicTestCase(0, 10 ,0 , 1422, false, DataRate("0Gb/s"), 0, DataRate("1Gb/s"), 65535, true, false, false), TestCase::QUICK);
|
||
|
|
// All packet should pass in yellow due to compling flag and dropOnYellow=true
|
||
|
|
AddTestCase(new PsfpBasicTestCase(0,10 ,0 , 1422, false, DataRate("1Gb/s"), 999, DataRate("0Gb/s"), 65535, true, true, false), TestCase::QUICK);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Do not forget to allocate an instance of this TestSuite
|
||
|
|
/**
|
||
|
|
* \ingroup psfp-tests
|
||
|
|
* Static variable for test initialization
|
||
|
|
*/
|
||
|
|
static PsfpTestSuite m_psfpTestSuite;
|