A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tgax-video-traffic-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 DERONNE SOFTWARE ENGINEERING
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "ns3/application-container.h"
10#include "ns3/application-helper.h"
11#include "ns3/config.h"
12#include "ns3/enum.h"
13#include "ns3/inet-socket-address.h"
14#include "ns3/internet-stack-helper.h"
15#include "ns3/ipv4-address-helper.h"
16#include "ns3/ipv4-address.h"
17#include "ns3/ipv4-interface-container.h"
18#include "ns3/ipv4-l3-protocol.h"
19#include "ns3/ipv4-list-routing-helper.h"
20#include "ns3/ipv4-static-routing-helper.h"
21#include "ns3/ipv4-static-routing.h"
22#include "ns3/node-container.h"
23#include "ns3/node.h"
24#include "ns3/nstime.h"
25#include "ns3/packet-sink-helper.h"
26#include "ns3/packet-sink.h"
27#include "ns3/rng-seed-manager.h"
28#include "ns3/simple-net-device-helper.h"
29#include "ns3/string.h"
30#include "ns3/test.h"
31#include "ns3/tgax-video-traffic.h"
32#include "ns3/traced-callback.h"
33
34#include <numeric>
35#include <optional>
36#include <string>
37#include <vector>
38
39using namespace ns3;
40
41NS_LOG_COMPONENT_DEFINE("TgaxVideoTrafficTest");
42
43namespace
44{
45
46/**
47 * Get the node ID from the context string.
48 *
49 * @param context the context string
50 * @return the corresponding node ID
51 */
53ConvertContextToNodeId(const std::string& context)
54{
55 auto sub = context.substr(10);
56 auto pos = sub.find("/Device");
57 return std::stoi(sub.substr(0, pos));
58}
59
60/**
61 * Get the string from the traffic model enum.
62 *
63 * @param model the traffic model enum
64 * @return the corresponding string
65 */
66std::string
93
94/**
95 * Get the expected average frame size.
96 *
97 * @param frameSizeBytesScale the scale of the Weibull distribution used to generate random frame
98 * sizes
99 * @param frameSizeBytesShape the shape of the Weibull distribution used to generate random frame
100 * sizes
101 * @return the expected average frame size
102 */
104GetAverageframeSize(double frameSizeBytesScale, double frameSizeBytesShape)
105{
107 return static_cast<uint32_t>(
108 WeibullRandomVariable::GetMean(frameSizeBytesScale, frameSizeBytesShape));
109}
110
111/**
112 * Get whether a model applies to multicast video traffic.
113 *
114 * @param model the traffic model
115 * @return true if the model is for multicast, false otherwise
116 */
117bool
123
124const auto simulationTime{Seconds(20)}; //!< The simulation time
125
126} // namespace
127
128/**
129 * @ingroup applications-test
130 * @ingroup tests
131 *
132 * TGax Video traffic test, check for the expected inter frame interval, bit rate and packets inter
133 * arrivals.
134 */
136{
137 public:
138 /**
139 * Constructor
140 *
141 * @param model the traffic model to use for the test
142 * @param protocol the protocol to use for the test (Udp or Tcp)
143 * @param expectedBitRate the expected bit rate in Mbps at the end of the test
144 * @param parameters optional traffic model parameters (used for custom traffic model)
145 * @param txBufferSizeLimit optional limit for the TX buffer size of the TCP socket
146 */
149 const std::string& protocol,
150 double expectedBitRate,
151 std::optional<TgaxVideoTraffic::TrafficModelParameters> parameters = {},
152 std::optional<uint32_t> txBufferSizeLimit = {});
153
154 private:
155 void DoSetup() override;
156 void DoRun() override;
157
158 /**
159 * Record a packets successfully sent
160 * @param packet the transmitted packet
161 * @param latency the latency applied to the packet
162 */
163 void PacketSent(Ptr<const Packet> packet, Time latency);
164
165 /**
166 * Record video frame generated
167 * @param size the size of the generated frame
168 */
169 void FrameGenerated(uint32_t size);
170
171 /**
172 * Record a packet successfully received
173 * @param context the context
174 * @param p the packet
175 * @param addr the sender's address
176 */
177 void ReceiveRx(std::string context, Ptr<const Packet> p, const Address& addr);
178
180 m_model; //!< Selected buffered video traffic model
181 std::string m_protocol; //!< Udp or Tcp protocol
182 std::optional<TgaxVideoTraffic::TrafficModelParameters>
183 m_parameters; //!< Optional traffic model parameters (used for custom traffic model)
184 std::optional<uint32_t>
185 m_txBufferSizeLimit; //!< Optional limit for the TX buffer size of the TCP socket
186
187 double m_expectedBitRate; //!< Expected video bit rate
188
189 uint64_t m_sent{0}; //!< number of bytes sent
190 std::vector<uint64_t> m_received; //!< number of bytes received per receiver
191 std::vector<Time> m_generatedFrames; //!< Store time at which each frame has been generated
192 std::vector<Time> m_latencies; //!< Store latency applied to each transmitted packet
193};
194
197 const std::string& protocol,
198 double expectedBitRate,
199 std::optional<TgaxVideoTraffic::TrafficModelParameters> parameters,
200 std::optional<uint32_t> txBufferSizeLimit)
201 : TestCase("Check video traffic with model " + ModelToString(model) + " and protocol " +
202 protocol),
203 m_model(model),
204 m_protocol(protocol),
205 m_parameters(parameters),
206 m_txBufferSizeLimit(txBufferSizeLimit),
207 m_expectedBitRate(expectedBitRate),
208 m_received(IsMulticast(m_model) ? 2 : 1, 0)
209{
210}
211
212void
214{
215 NS_LOG_FUNCTION(this << packet << packet->GetSize() << latency);
216 m_sent += packet->GetSize();
217 m_latencies.push_back(latency);
218}
219
220void
226
227void
229{
230 const auto receiver = ConvertContextToNodeId(context) - 1;
231 NS_LOG_FUNCTION(this << receiver << p << addr << p->GetSize());
232 m_received.at(receiver) += p->GetSize();
233}
234
235void
237{
238 NS_LOG_FUNCTION(this);
239
240 // LogComponentEnable("TgaxVideoTrafficTest", LOG_LEVEL_ALL);
241 // LogComponentEnable("TgaxVideoTraffic", LOG_LEVEL_ALL);
242 // LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
243
246
247 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1500));
248 Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(1));
250 {
251 Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(*m_txBufferSizeLimit));
252 }
253
254 uint16_t port = 90;
255 const std::string multicastAddress = "239.192.100.1";
256
257 auto sender = CreateObject<Node>();
258 NodeContainer receivers(m_received.size());
259
261 nodes.Add(sender);
262 nodes.Add(receivers);
263
264 SimpleNetDeviceHelper simpleHelper;
265 auto devices = simpleHelper.Install(nodes);
266
267 Ipv4StaticRoutingHelper staticRouting;
268 InternetStackHelper internet;
269 if (IsMulticast(m_model))
270 {
271 Ipv4ListRoutingHelper listRouting;
272 listRouting.Add(staticRouting, 0);
273 internet.SetRoutingHelper(listRouting);
274 }
275 internet.Install(nodes);
276
277 Ipv4AddressHelper ipv4Helper;
278 ipv4Helper.SetBase("10.11.12.0", "255.255.255.0");
279 auto interfaces = ipv4Helper.Assign(devices);
280
281 if (IsMulticast(m_model))
282 {
283 auto ipv4 = sender->GetObject<Ipv4>();
284 auto routing = staticRouting.GetStaticRouting(ipv4);
285 routing->AddHostRouteTo(multicastAddress.c_str(),
286 ipv4->GetInterfaceForDevice(sender->GetDevice(0)),
287 0);
288 }
289
291 auto remoteAddress = InetSocketAddress(IsMulticast(m_model) ? multicastAddress.c_str()
292 : interfaces.GetAddress(1),
293 port);
294 sourceHelper.SetAttribute("Remote", AddressValue(remoteAddress));
295 const std::string protocol = "ns3::" + m_protocol + "SocketFactory";
296 sourceHelper.SetAttribute("Protocol", StringValue(protocol));
297 sourceHelper.SetAttribute("TrafficModelClassIdentifier", EnumValue(m_model));
298 sourceHelper.SetAttribute("LatencyScale", DoubleValue(60.227));
299 if (m_parameters)
300 {
301 sourceHelper.SetAttribute("CustomVideoBitRate", DataRateValue(m_parameters->bitRate));
302 sourceHelper.SetAttribute("CustomFrameSizeScale",
303 DoubleValue(m_parameters->frameSizeBytesScale));
304 sourceHelper.SetAttribute("CustomFrameSizeShape",
305 DoubleValue(m_parameters->frameSizeBytesShape));
306 }
307 auto sourceApp = sourceHelper.Install(sender);
308 sourceApp.Start(Seconds(1.0));
309 sourceApp.Stop(Seconds(1.0) + simulationTime);
310
312 auto sinkApps = sinkHelper.Install(receivers);
313 sinkApps.Start(Seconds(0.0));
314 sinkApps.Stop(Seconds(2.0) + simulationTime);
315
316 int64_t streamNumber = 55;
317 sourceHelper.AssignStreams(nodes, streamNumber);
318
320 "/NodeList/*/$ns3::Node/ApplicationList/*/$ns3::TgaxVideoTraffic/TxWithLatency",
322
324 "/NodeList/*/$ns3::Node/ApplicationList/*/$ns3::TgaxVideoTraffic/VideoFrameGenerated",
326
327 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx",
329}
330
331void
333{
334 NS_LOG_FUNCTION(this);
335
338
339 for (std::size_t i = 0; i < m_received.size(); ++i)
340 {
342 m_received.at(i),
343 "Did not receive all transmitted video frames for receiver " << i);
344 const auto measuredBitrate =
345 static_cast<double>(m_received.at(i) * 8) / simulationTime.GetMicroSeconds();
346 NS_TEST_EXPECT_MSG_EQ_TOL(measuredBitrate,
348 0.05 * m_expectedBitRate,
349 "Unexpected video bit rate " << measuredBitrate
350 << " for receiver " << i);
351 }
352
353 const auto averageFrameSize =
354 (m_parameters) ? GetAverageframeSize(m_parameters->frameSizeBytesScale,
355 m_parameters->frameSizeBytesShape)
357 TgaxVideoTraffic::m_trafficModels.at(m_model).frameSizeBytesScale,
358 TgaxVideoTraffic::m_trafficModels.at(m_model).frameSizeBytesShape);
359 const auto expectedInterFrameDuration =
360 static_cast<double>(averageFrameSize * 8) / m_expectedBitRate;
361 std::vector<Time> interFrameDurations;
362 std::transform(m_generatedFrames.cbegin(),
363 m_generatedFrames.cend() - 1,
364 m_generatedFrames.cbegin() + 1,
365 std::back_inserter(interFrameDurations),
366 [](const auto& lhs, const auto& rhs) { return (rhs - lhs); });
367 const auto totalInterFrameDurations =
368 std::accumulate(interFrameDurations.cbegin(),
369 interFrameDurations.cend(),
370 Time(),
371 [](auto sum, const auto t) { return sum + t; });
372 const auto interFrameDuration = totalInterFrameDurations / interFrameDurations.size();
373 NS_TEST_EXPECT_MSG_EQ_TOL(interFrameDuration.GetMicroSeconds(),
374 expectedInterFrameDuration,
375 1,
376 "Unexpected frame interval");
377
378 const auto totalLatency = std::accumulate(m_latencies.cbegin(),
379 m_latencies.cend(),
380 Time(),
381 [](auto sum, auto latency) { return sum + latency; });
382 const auto avgLatency = totalLatency / m_latencies.size();
383 NS_TEST_EXPECT_MSG_EQ_TOL(avgLatency.GetMicroSeconds(),
384 14834,
385 200,
386 "Unexpected average networking latency");
387}
388
389/**
390 * @ingroup applications-test
391 * @ingroup tests
392 *
393 * @brief TgaxVideoTraffic TestSuite
394 */
396{
397 public:
399};
400
402 : TestSuite("applications-tgax-video-traffic", Type::UNIT)
403{
404 for (const auto& protocol : {"Tcp", "Udp"})
405 {
408 protocol,
409 2.0),
413 protocol,
414 4.0),
418 protocol,
419 6.0),
423 protocol,
424 8.0),
428 protocol,
429 10.0),
433 protocol,
434 15.6),
436 }
439 "Udp",
440 3.0),
444 "Udp",
445 6.0),
448 "Udp",
449 5.0,
450 {{DataRate("5Mbps"), 5000, 0.5}}),
453 "Tcp",
454 20.0,
455 {{DataRate("20Mbps"), 15000, 1.0}}),
458 "Tcp",
459 20.0,
460 {{DataRate("20Mbps"), 15000, 1.0}},
461 1500),
463}
464
466 g_TgaxVideoTrafficTestSuite; //!< Static variable for test initialization
TGax Video traffic test, check for the expected inter frame interval, bit rate and packets inter arri...
std::vector< Time > m_latencies
Store latency applied to each transmitted packet.
std::vector< uint64_t > m_received
number of bytes received per receiver
void FrameGenerated(uint32_t size)
Record video frame generated.
std::optional< uint32_t > m_txBufferSizeLimit
Optional limit for the TX buffer size of the TCP socket.
void DoRun() override
Implementation to actually run this TestCase.
TgaxVideoTraffic::TrafficModelClassIdentifier m_model
Selected buffered video traffic model.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
TgaxVideoTrafficTestCase(TgaxVideoTraffic::TrafficModelClassIdentifier model, const std::string &protocol, double expectedBitRate, std::optional< TgaxVideoTraffic::TrafficModelParameters > parameters={}, std::optional< uint32_t > txBufferSizeLimit={})
Constructor.
std::string m_protocol
Udp or Tcp protocol.
std::optional< TgaxVideoTraffic::TrafficModelParameters > m_parameters
Optional traffic model parameters (used for custom traffic model).
std::vector< Time > m_generatedFrames
Store time at which each frame has been generated.
double m_expectedBitRate
Expected video bit rate.
void ReceiveRx(std::string context, Ptr< const Packet > p, const Address &addr)
Record a packet successfully received.
void PacketSent(Ptr< const Packet > packet, Time latency)
Record a packets successfully sent.
uint64_t m_sent
number of bytes sent
a polymophic address class
Definition address.h:114
AttributeValue implementation for Address.
Definition address.h:329
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
A helper to make it easier to instantiate an application on a set of nodes.
ApplicationContainer Install(NodeContainer c)
Install an application on each node of the input container configured with all the attributes set wit...
int64_t AssignStreams(NodeContainer c, int64_t stream)
Assigns a unique (monotonically increasing) stream number to all applications that match the configur...
void SetAttribute(const std::string &name, const AttributeValue &value)
Helper function used to set the underlying application attributes.
Class for representing data rates.
Definition data-rate.h:78
AttributeValue implementation for DataRate.
Definition data-rate.h:252
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
Hold variables of type enum.
Definition enum.h:52
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
static Ipv4Address GetAny()
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition ipv4.h:69
Helper class that adds ns3::Ipv4ListRouting objects.
void Add(const Ipv4RoutingHelper &routing, int16_t priority)
Helper class that adds ns3::Ipv4StaticRouting objects.
Ptr< Ipv4StaticRouting > GetStaticRouting(Ptr< Ipv4 > ipv4) const
Try and find the static routing protocol as either the main routing protocol or in the list of routin...
keep track of a set of node pointers.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
build a set of SimpleNetDevice objects
NetDeviceContainer Install(Ptr< Node > node) const
This method creates an ns3::SimpleChannel with the attributes configured by SimpleNetDeviceHelper::Se...
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:125
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
static void Run()
Run the simulation.
Definition simulator.cc:161
Hold variables of type string.
Definition string.h:45
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:296
@ QUICK
Fast test.
Definition test.h:1057
TestCase(const TestCase &)=delete
Caller graph was not generated because of its size.
Type
Type of test.
Definition test.h:1271
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:494
static const TrafficModels m_trafficModels
Traffic models as defined in Table 5 from IEEE 802.11-14/0571r12 - 11ax Evaluation Methodology.
static TypeId GetTypeId()
Get the type ID.
TrafficModelClassIdentifier
TrafficModelClassIdentifier enumeration.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
Hold an unsigned integer type.
Definition uinteger.h:34
double GetMean() const
Returns the mean value for the Weibull distribution returned by this RNG stream.
uint16_t port
Definition dsdv-manet.cc:33
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:690
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:886
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:970
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition config.cc:946
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:133
#define NS_TEST_EXPECT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report if ...
Definition test.h:499
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
NodeContainer nodes
bool IsMulticast(TgaxVideoTraffic::TrafficModelClassIdentifier model)
Get whether a model applies to multicast video traffic.
uint32_t ConvertContextToNodeId(const std::string &context)
Get the node ID from the context string.
std::string ModelToString(TgaxVideoTraffic::TrafficModelClassIdentifier model)
Get the string from the traffic model enum.
uint32_t GetAverageframeSize(double frameSizeBytesScale, double frameSizeBytesShape)
Get the expected average frame size.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TgaxVideoTrafficTestSuite g_TgaxVideoTrafficTestSuite
Static variable for test initialization.