A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-80211e-txop.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 Sébastien Deronne
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
18 */
19
20#include "ns3/command-line.h"
21#include "ns3/internet-stack-helper.h"
22#include "ns3/ipv4-address-helper.h"
23#include "ns3/log.h"
24#include "ns3/mobility-helper.h"
25#include "ns3/on-off-helper.h"
26#include "ns3/pointer.h"
27#include "ns3/qos-txop.h"
28#include "ns3/ssid.h"
29#include "ns3/string.h"
30#include "ns3/udp-client-server-helper.h"
31#include "ns3/wifi-mac.h"
32#include "ns3/wifi-net-device.h"
33#include "ns3/yans-wifi-channel.h"
34#include "ns3/yans-wifi-helper.h"
35
36// This is an example that illustrates 802.11 QoS for different Access Categories.
37// It defines 4 independent Wi-Fi networks (working on different logical channels
38// on the same "ns3::YansWifiPhy" channel object).
39// Each network contains one access point and one station. Each station continuously
40// transmits data packets to its respective AP.
41//
42// Network topology (numbers in parentheses are channel numbers):
43//
44// BSS A (36) BSS B (40) BSS C (44) BSS D (48)
45// * * * * * * * *
46// | | | | | | | |
47// AP A STA A AP B STA B AP C STA C AP D STA D
48//
49// The configuration is the following on the 4 networks:
50// - STA A sends AC_BE traffic to AP A with default AC_BE TXOP value of 0 (1 MSDU);
51// - STA B sends AC_BE traffic to AP B with non-default AC_BE TXOP of 4096 us;
52// - STA C sends AC_VI traffic to AP C with default AC_VI TXOP of 4096 us;
53// - STA D sends AC_VI traffic to AP D with non-default AC_VI TXOP value of 0 (1 MSDU);
54//
55// The user can select the distance between the stations and the APs, can enable/disable the RTS/CTS
56// mechanism and can choose the payload size and the simulation duration. Example: ./ns3 run
57// "wifi-80211e-txop --distance=10 --simulationTime=20 --payloadSize=1000"
58//
59// The output prints the throughput measured for the 4 cases/networks described above. When TXOP is
60// enabled, results show increased throughput since the channel is granted for a longer duration.
61// TXOP is enabled by default for AC_VI and AC_VO, so that they can use the channel for a longer
62// duration than AC_BE and AC_BK.
63
64using namespace ns3;
65
66NS_LOG_COMPONENT_DEFINE("80211eTxop");
67
72{
80 void Trace(Time startTime, Time duration, uint8_t linkId);
82};
83
84void
85TxopDurationTracer::Trace(Time startTime, Time duration, uint8_t linkId)
86{
87 if (duration > m_max)
88 {
89 m_max = duration;
90 }
91}
92
93int
94main(int argc, char* argv[])
95{
96 uint32_t payloadSize = 1472; // bytes
97 double simulationTime = 10; // seconds
98 double distance = 5; // meters
99 bool enablePcap = 0;
100 bool verifyResults = 0; // used for regression
101 Time txopLimit = MicroSeconds(4096);
102
103 CommandLine cmd(__FILE__);
104 cmd.AddValue("payloadSize", "Payload size in bytes", payloadSize);
105 cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime);
106 cmd.AddValue("distance",
107 "Distance in meters between the station and the access point",
108 distance);
109 cmd.AddValue("enablePcap", "Enable/disable pcap file generation", enablePcap);
110 cmd.AddValue("verifyResults",
111 "Enable/disable results verification at the end of the simulation",
112 verifyResults);
113 cmd.Parse(argc, argv);
114
115 NodeContainer wifiStaNodes;
116 wifiStaNodes.Create(4);
117 NodeContainer wifiApNodes;
118 wifiApNodes.Create(4);
119
122 phy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11_RADIO);
123 phy.SetChannel(channel.Create());
124
125 WifiHelper wifi;
126 wifi.SetStandard(WIFI_STANDARD_80211a);
127 wifi.SetRemoteStationManager("ns3::IdealWifiManager");
128 WifiMacHelper mac;
129
130 NetDeviceContainer staDeviceA;
131 NetDeviceContainer staDeviceB;
132 NetDeviceContainer staDeviceC;
133 NetDeviceContainer staDeviceD;
134 NetDeviceContainer apDeviceA;
135 NetDeviceContainer apDeviceB;
136 NetDeviceContainer apDeviceC;
137 NetDeviceContainer apDeviceD;
138 Ssid ssid;
139
140 // Network A
141 ssid = Ssid("network-A");
142 phy.Set("ChannelSettings", StringValue("{36, 20, BAND_5GHZ, 0}"));
143 mac.SetType("ns3::StaWifiMac", "QosSupported", BooleanValue(true), "Ssid", SsidValue(ssid));
144 staDeviceA = wifi.Install(phy, mac, wifiStaNodes.Get(0));
145
146 mac.SetType("ns3::ApWifiMac",
147 "QosSupported",
148 BooleanValue(true),
149 "Ssid",
150 SsidValue(ssid),
151 "EnableBeaconJitter",
152 BooleanValue(false));
153 apDeviceA = wifi.Install(phy, mac, wifiApNodes.Get(0));
154
155 // Network B
156 ssid = Ssid("network-B");
157 phy.Set("ChannelSettings", StringValue("{40, 20, BAND_5GHZ, 0}"));
158 mac.SetType("ns3::StaWifiMac", "QosSupported", BooleanValue(true), "Ssid", SsidValue(ssid));
159
160 staDeviceB = wifi.Install(phy, mac, wifiStaNodes.Get(1));
161
162 mac.SetType("ns3::ApWifiMac",
163 "QosSupported",
164 BooleanValue(true),
165 "Ssid",
166 SsidValue(ssid),
167 "EnableBeaconJitter",
168 BooleanValue(false));
169 apDeviceB = wifi.Install(phy, mac, wifiApNodes.Get(1));
170
171 // Modify EDCA configuration (TXOP limit) for AC_BE
172 Ptr<NetDevice> dev = wifiApNodes.Get(1)->GetDevice(0);
173 Ptr<WifiNetDevice> wifi_dev = DynamicCast<WifiNetDevice>(dev);
174 Ptr<WifiMac> wifi_mac = wifi_dev->GetMac();
175 PointerValue ptr;
176 Ptr<QosTxop> edca;
177 wifi_mac->GetAttribute("BE_Txop", ptr);
178 edca = ptr.Get<QosTxop>();
179 edca->SetTxopLimit(txopLimit);
180
181 // Trace TXOP duration for BE on STA1
182 dev = wifiStaNodes.Get(1)->GetDevice(0);
183 wifi_dev = DynamicCast<WifiNetDevice>(dev);
184 wifi_mac = wifi_dev->GetMac();
185 wifi_mac->GetAttribute("BE_Txop", ptr);
186 edca = ptr.Get<QosTxop>();
187 TxopDurationTracer beTxopTracer;
188 edca->TraceConnectWithoutContext("TxopTrace",
189 MakeCallback(&TxopDurationTracer::Trace, &beTxopTracer));
190
191 // Network C
192 ssid = Ssid("network-C");
193 phy.Set("ChannelSettings", StringValue("{44, 20, BAND_5GHZ, 0}"));
194 mac.SetType("ns3::StaWifiMac", "QosSupported", BooleanValue(true), "Ssid", SsidValue(ssid));
195
196 staDeviceC = wifi.Install(phy, mac, wifiStaNodes.Get(2));
197
198 mac.SetType("ns3::ApWifiMac",
199 "QosSupported",
200 BooleanValue(true),
201 "Ssid",
202 SsidValue(ssid),
203 "EnableBeaconJitter",
204 BooleanValue(false));
205 apDeviceC = wifi.Install(phy, mac, wifiApNodes.Get(2));
206
207 // Trace TXOP duration for VI on STA2
208 dev = wifiStaNodes.Get(2)->GetDevice(0);
209 wifi_dev = DynamicCast<WifiNetDevice>(dev);
210 wifi_mac = wifi_dev->GetMac();
211 wifi_mac->GetAttribute("VI_Txop", ptr);
212 edca = ptr.Get<QosTxop>();
213 TxopDurationTracer viTxopTracer;
214 edca->TraceConnectWithoutContext("TxopTrace",
215 MakeCallback(&TxopDurationTracer::Trace, &viTxopTracer));
216
217 // Network D
218 ssid = Ssid("network-D");
219 phy.Set("ChannelSettings", StringValue("{48, 20, BAND_5GHZ, 0}"));
220 mac.SetType("ns3::StaWifiMac", "QosSupported", BooleanValue(true), "Ssid", SsidValue(ssid));
221
222 staDeviceD = wifi.Install(phy, mac, wifiStaNodes.Get(3));
223
224 mac.SetType("ns3::ApWifiMac",
225 "QosSupported",
226 BooleanValue(true),
227 "Ssid",
228 SsidValue(ssid),
229 "EnableBeaconJitter",
230 BooleanValue(false));
231 apDeviceD = wifi.Install(phy, mac, wifiApNodes.Get(3));
232
233 // Modify EDCA configuration (TXOP limit) for AC_VO
234 dev = wifiApNodes.Get(3)->GetDevice(0);
235 wifi_dev = DynamicCast<WifiNetDevice>(dev);
236 wifi_mac = wifi_dev->GetMac();
237 wifi_mac->GetAttribute("VI_Txop", ptr);
238 edca = ptr.Get<QosTxop>();
239 edca->SetTxopLimit(MicroSeconds(0));
240
241 /* Setting mobility model */
242 MobilityHelper mobility;
243 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
244 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
245
246 // Set position for APs
247 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
248 positionAlloc->Add(Vector(10.0, 0.0, 0.0));
249 positionAlloc->Add(Vector(20.0, 0.0, 0.0));
250 positionAlloc->Add(Vector(30.0, 0.0, 0.0));
251 // Set position for STAs
252 positionAlloc->Add(Vector(distance, 0.0, 0.0));
253 positionAlloc->Add(Vector(10 + distance, 0.0, 0.0));
254 positionAlloc->Add(Vector(20 + distance, 0.0, 0.0));
255 positionAlloc->Add(Vector(30 + distance, 0.0, 0.0));
256 // Remark: while we set these positions 10 meters apart, the networks do not interact
257 // and the only variable that affects transmission performance is the distance.
258
259 mobility.SetPositionAllocator(positionAlloc);
260 mobility.Install(wifiApNodes);
261 mobility.Install(wifiStaNodes);
262
263 /* Internet stack */
265 stack.Install(wifiApNodes);
266 stack.Install(wifiStaNodes);
267
268 Ipv4AddressHelper address;
269 address.SetBase("192.168.1.0", "255.255.255.0");
270 Ipv4InterfaceContainer StaInterfaceA;
271 StaInterfaceA = address.Assign(staDeviceA);
272 Ipv4InterfaceContainer ApInterfaceA;
273 ApInterfaceA = address.Assign(apDeviceA);
274
275 address.SetBase("192.168.2.0", "255.255.255.0");
276 Ipv4InterfaceContainer StaInterfaceB;
277 StaInterfaceB = address.Assign(staDeviceB);
278 Ipv4InterfaceContainer ApInterfaceB;
279 ApInterfaceB = address.Assign(apDeviceB);
280
281 address.SetBase("192.168.3.0", "255.255.255.0");
282 Ipv4InterfaceContainer StaInterfaceC;
283 StaInterfaceC = address.Assign(staDeviceC);
284 Ipv4InterfaceContainer ApInterfaceC;
285 ApInterfaceC = address.Assign(apDeviceC);
286
287 address.SetBase("192.168.4.0", "255.255.255.0");
288 Ipv4InterfaceContainer StaInterfaceD;
289 StaInterfaceD = address.Assign(staDeviceD);
290 Ipv4InterfaceContainer ApInterfaceD;
291 ApInterfaceD = address.Assign(apDeviceD);
292
293 /* Setting applications */
294 uint16_t port = 5001;
295 UdpServerHelper serverA(port);
296 ApplicationContainer serverAppA = serverA.Install(wifiApNodes.Get(0));
297 serverAppA.Start(Seconds(0.0));
298 serverAppA.Stop(Seconds(simulationTime + 1));
299
300 InetSocketAddress destA(ApInterfaceA.GetAddress(0), port);
301 destA.SetTos(0x70); // AC_BE
302
303 OnOffHelper clientA("ns3::UdpSocketFactory", destA);
304 clientA.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
305 clientA.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
306 clientA.SetAttribute("DataRate", StringValue("100000kb/s"));
307 clientA.SetAttribute("PacketSize", UintegerValue(payloadSize));
308
309 ApplicationContainer clientAppA = clientA.Install(wifiStaNodes.Get(0));
310 clientAppA.Start(Seconds(1.0));
311 clientAppA.Stop(Seconds(simulationTime + 1));
312
313 UdpServerHelper serverB(port);
314 ApplicationContainer serverAppB = serverB.Install(wifiApNodes.Get(1));
315 serverAppB.Start(Seconds(0.0));
316 serverAppB.Stop(Seconds(simulationTime + 1));
317
318 InetSocketAddress destB(ApInterfaceB.GetAddress(0), port);
319 destB.SetTos(0x70); // AC_BE
320
321 OnOffHelper clientB("ns3::UdpSocketFactory", destB);
322 clientB.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
323 clientB.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
324 clientB.SetAttribute("DataRate", StringValue("100000kb/s"));
325 clientB.SetAttribute("PacketSize", UintegerValue(payloadSize));
326
327 ApplicationContainer clientAppB = clientB.Install(wifiStaNodes.Get(1));
328 clientAppB.Start(Seconds(1.0));
329 clientAppB.Stop(Seconds(simulationTime + 1));
330
331 UdpServerHelper serverC(port);
332 ApplicationContainer serverAppC = serverC.Install(wifiApNodes.Get(2));
333 serverAppC.Start(Seconds(0.0));
334 serverAppC.Stop(Seconds(simulationTime + 1));
335
336 InetSocketAddress destC(ApInterfaceC.GetAddress(0), port);
337 destC.SetTos(0xb8); // AC_VI
338
339 OnOffHelper clientC("ns3::UdpSocketFactory", destC);
340 clientC.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
341 clientC.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
342 clientC.SetAttribute("DataRate", StringValue("100000kb/s"));
343 clientC.SetAttribute("PacketSize", UintegerValue(payloadSize));
344
345 ApplicationContainer clientAppC = clientC.Install(wifiStaNodes.Get(2));
346 clientAppC.Start(Seconds(1.0));
347 clientAppC.Stop(Seconds(simulationTime + 1));
348
349 UdpServerHelper serverD(port);
350 ApplicationContainer serverAppD = serverD.Install(wifiApNodes.Get(3));
351 serverAppD.Start(Seconds(0.0));
352 serverAppD.Stop(Seconds(simulationTime + 1));
353
354 InetSocketAddress destD(ApInterfaceD.GetAddress(0), port);
355 destD.SetTos(0xb8); // AC_VI
356
357 OnOffHelper clientD("ns3::UdpSocketFactory", destD);
358 clientD.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
359 clientD.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
360 clientD.SetAttribute("DataRate", StringValue("100000kb/s"));
361 clientD.SetAttribute("PacketSize", UintegerValue(payloadSize));
362
363 ApplicationContainer clientAppD = clientD.Install(wifiStaNodes.Get(3));
364 clientAppD.Start(Seconds(1.0));
365 clientAppD.Stop(Seconds(simulationTime + 1));
366
367 if (enablePcap)
368 {
369 phy.EnablePcap("AP_A", apDeviceA.Get(0));
370 phy.EnablePcap("STA_A", staDeviceA.Get(0));
371 phy.EnablePcap("AP_B", apDeviceB.Get(0));
372 phy.EnablePcap("STA_B", staDeviceB.Get(0));
373 phy.EnablePcap("AP_C", apDeviceC.Get(0));
374 phy.EnablePcap("STA_C", staDeviceC.Get(0));
375 phy.EnablePcap("AP_D", apDeviceD.Get(0));
376 phy.EnablePcap("STA_D", staDeviceD.Get(0));
377 }
378
379 Simulator::Stop(Seconds(simulationTime + 1));
381
382 /* Show results */
383 uint64_t totalPacketsThroughA = DynamicCast<UdpServer>(serverAppA.Get(0))->GetReceived();
384 uint64_t totalPacketsThroughB = DynamicCast<UdpServer>(serverAppB.Get(0))->GetReceived();
385 uint64_t totalPacketsThroughC = DynamicCast<UdpServer>(serverAppC.Get(0))->GetReceived();
386 uint64_t totalPacketsThroughD = DynamicCast<UdpServer>(serverAppD.Get(0))->GetReceived();
387
389
390 double throughput = totalPacketsThroughA * payloadSize * 8 / (simulationTime * 1000000.0);
391 std::cout << "AC_BE with default TXOP limit (0ms): " << '\n'
392 << " Throughput = " << throughput << " Mbit/s" << '\n';
393 if (verifyResults && (throughput < 28 || throughput > 29))
394 {
395 NS_LOG_ERROR("Obtained throughput " << throughput << " is not in the expected boundaries!");
396 exit(1);
397 }
398
399 throughput = totalPacketsThroughB * payloadSize * 8 / (simulationTime * 1000000.0);
400 std::cout << "AC_BE with non-default TXOP limit (4.096ms): " << '\n'
401 << " Throughput = " << throughput << " Mbit/s" << '\n';
402 if (verifyResults && (throughput < 36.5 || throughput > 37))
403 {
404 NS_LOG_ERROR("Obtained throughput " << throughput << " is not in the expected boundaries!");
405 exit(1);
406 }
407 std::cout << " Maximum TXOP duration = " << beTxopTracer.m_max.GetMicroSeconds() << " us"
408 << '\n';
409 if (verifyResults &&
410 (beTxopTracer.m_max < MicroSeconds(3008) || beTxopTracer.m_max > txopLimit))
411 {
412 NS_LOG_ERROR("Maximum TXOP duration " << beTxopTracer.m_max
413 << " is not in the expected boundaries!");
414 exit(1);
415 }
416
417 throughput = totalPacketsThroughC * payloadSize * 8 / (simulationTime * 1000000.0);
418 std::cout << "AC_VI with default TXOP limit (4.096ms): " << '\n'
419 << " Throughput = " << throughput << " Mbit/s" << '\n';
420 if (verifyResults && (throughput < 36.5 || throughput > 37.5))
421 {
422 NS_LOG_ERROR("Obtained throughput " << throughput << " is not in the expected boundaries!");
423 exit(1);
424 }
425 std::cout << " Maximum TXOP duration = " << viTxopTracer.m_max.GetMicroSeconds() << " us"
426 << '\n';
427 if (verifyResults &&
428 (viTxopTracer.m_max < MicroSeconds(3008) || viTxopTracer.m_max > txopLimit))
429 {
430 NS_LOG_ERROR("Maximum TXOP duration " << viTxopTracer.m_max
431 << " is not in the expected boundaries!");
432 exit(1);
433 }
434
435 throughput = totalPacketsThroughD * payloadSize * 8 / (simulationTime * 1000000.0);
436 std::cout << "AC_VI with non-default TXOP limit (0ms): " << '\n'
437 << " Throughput = " << throughput << " Mbit/s" << '\n';
438 if (verifyResults && (throughput < 31.5 || throughput > 32.5))
439 {
440 NS_LOG_ERROR("Obtained throughput " << throughput << " is not in the expected boundaries!");
441 exit(1);
442 }
443
444 return 0;
445}
holds a vector of ns3::Application pointers.
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
void Stop(Time stop) const
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Parse command-line arguments.
Definition: command-line.h:232
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.
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:152
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
Definition: on-off-helper.h:44
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:202
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:72
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:140
static void Run()
Run the simulation.
Definition: simulator.cc:176
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:184
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
Create a server application which waits for input UDP packets and uses the information carried into t...
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
create MAC layers for a ns3::WifiNetDevice.
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
Definition: wifi-helper.h:178
manage and create wifi channel objects for the YANS model.
static YansWifiChannelHelper Default()
Create a channel helper in a default working state.
Make it easy to create and manage PHY objects for the YANS model.
uint16_t port
Definition: dsdv-manet.cc:44
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
@ WIFI_STANDARD_80211a
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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:702
Keeps the maximum duration among all TXOPs.
void Trace(Time startTime, Time duration, uint8_t linkId)
Callback connected to TXOP duration trace source.
Time m_max
maximum TXOP duration