// 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 p); void ReceiveRx(Ptr 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 p) { m_sent += p->GetSize(); } void PsfpBasicTestCase::ReceiveRx(Ptr 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 n0 = CreateObject(); Ptr n1 = CreateObject(); //Create and add a netDevice to each node Ptr net0 = CreateObject(); n0->AddDevice(net0); Ptr net1 = CreateObject(); n1->AddDevice(net1); //Create a Tsn Channel and attach it two the two netDevices Ptr channel = CreateObject(); 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>()); net0->SetQueue(CreateObject>()); net1->SetQueue(CreateObject>()); net1->SetQueue(CreateObject>()); //Stream identification Ptr sif0 = CreateObject(); 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 sfi0 = CreateObject(); 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 fm0 = CreateObject(); 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 app0 = CreateObject(); 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 app1 = CreateObject(); 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;