A Discrete-Event Network Simulator
API
bs-uplink-scheduler-mbqos.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation;
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 *
16 */
17
19#include "bs-net-device.h"
20#include "ns3/simulator.h"
21#include "cid.h"
23#include "ss-manager.h"
24#include "ns3/log.h"
25#include "ns3/uinteger.h"
26#include "service-flow.h"
27#include "service-flow-record.h"
28#include "bs-link-manager.h"
29#include "bandwidth-manager.h"
30#include "connection-manager.h"
31
32namespace ns3 {
33
34NS_LOG_COMPONENT_DEFINE ("UplinkSchedulerMBQoS");
35
36NS_OBJECT_ENSURE_REGISTERED (UplinkSchedulerMBQoS);
37
39{
40}
41
43 : m_windowInterval (time)
44{
45
46}
47
49{
50 SetBs (0);
51 m_uplinkAllocations.clear ();
52}
53
56{
57 static TypeId tid = TypeId ("ns3::UplinkSchedulerMBQoS")
58
60
61 .SetGroupName("Wimax")
62
63 .AddAttribute ("WindowInterval",
64 "The time to wait to reset window",
65 TimeValue (Seconds (1.0)),
68 return tid;
69}
70
71void
73{
75}
76
77std::list<OfdmUlMapIe>
79{
81}
82
83void
85 bool &updateUcd,
86 bool &sendDcd,
87 bool &sendUcd)
88{
89 /* DCD and UCD shall actually be updated when channel or burst profile definitions
90 change. burst profiles are updated based on number of SSs, network conditions and etc.
91 for now temporarily assuming DCD/UCD shall be updated every time */
92
93 uint32_t randNr = rand ();
94 if (randNr % 5 == 0 || GetBs ()->GetNrDcdSent () == 0)
95 {
96 sendDcd = true;
97 }
98
99 randNr = rand ();
100 if (randNr % 5 == 0 || GetBs ()->GetNrUcdSent () == 0)
101 {
102 sendUcd = true;
103 }
104
105 // -------------------------------------
106 // additional, just to send more frequently
107 if (!sendDcd)
108 {
109 randNr = rand ();
110 if (randNr % 4 == 0)
111 {
112 sendDcd = true;
113 }
114 }
115
116 if (!sendUcd)
117 {
118 randNr = rand ();
119 if (randNr % 4 == 0)
120 {
121 sendUcd = true;
122 }
123 }
124 // -------------------------------------
125
126 Time timeSinceLastDcd = Simulator::Now () - GetDcdTimeStamp ();
127 Time timeSinceLastUcd = Simulator::Now () - GetUcdTimeStamp ();
128
129 if (timeSinceLastDcd > GetBs ()->GetDcdInterval ())
130 {
131 sendDcd = true;
133 }
134
135 if (timeSinceLastUcd > GetBs ()->GetUcdInterval ())
136 {
137 sendUcd = true;
139 }
140}
141
144{
145 return GetBs ()->GetNrDlSymbols () * GetBs ()->GetPhy ()->GetPsPerSymbol () + GetBs ()->GetTtg ();
146}
147
148void
150 const uint32_t &allocationSize,
151 uint32_t &symbolsToAllocation,
152 uint32_t &availableSymbols)
153{
154 ulMapIe.SetDuration (allocationSize);
155 ulMapIe.SetStartTime (symbolsToAllocation);
156 m_uplinkAllocations.push_back (ulMapIe);
157 symbolsToAllocation += allocationSize;
158 availableSymbols -= allocationSize;
159}
160
161void
163{
164
165 NS_LOG (LOG_DEBUG, "Window Reset at " << (Simulator::Now ()).As (Time::S));
166
167 uint32_t min_bw = 0;
168
169 if (!GetBs ()->GetSSManager ())
170 {
172 return;
173 }
174
175 std::vector<SSRecord*> *ssRecords = GetBs ()->GetSSManager ()->GetSSRecords ();
176
177 // For each SS
178 for (std::vector<SSRecord*>::iterator iter = ssRecords->begin (); iter != ssRecords->end (); ++iter)
179 {
180 SSRecord *ssRecord = *iter;
181 std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows (ServiceFlow::SF_TYPE_ALL);
182
183 // For each flow
184 for (std::vector<ServiceFlow*>::iterator iter2 = serviceFlows.begin (); iter2 != serviceFlows.end (); ++iter2)
185 {
186 ServiceFlow *serviceFlow = *iter2;
187 if ((serviceFlow->GetSchedulingType () == ServiceFlow::SF_TYPE_RTPS) || (serviceFlow->GetSchedulingType ()
189 {
190 min_bw = (int) ceil (serviceFlow->GetMinReservedTrafficRate ());
191
192 // This way we can compensate flows which did not get min_bw in the previous window
193 if ((serviceFlow->GetRecord ()->GetBacklogged () > 0)
194 && (serviceFlow->GetRecord ()->GetBwSinceLastExpiry () < min_bw))
195 {
196 serviceFlow->GetRecord ()->UpdateBwSinceLastExpiry (-min_bw);
197
198 // if backlogged < granted_bw then we don't need to provide granted_bw + min_bw in next window, but backlogged + min_bw
199 if (serviceFlow->GetRecord ()->GetBacklogged ()
200 < (serviceFlow->GetRecord ()->GetBwSinceLastExpiry ()))
201 {
202 serviceFlow->GetRecord ()->SetBwSinceLastExpiry (-serviceFlow->GetRecord ()->GetBacklogged ());
203 }
204 }
205 else
206 {
207 serviceFlow->GetRecord ()->SetBwSinceLastExpiry (0);
208 }
209 }
210 }
211 }
212
213 // Periodically reset window
215}
216
217void
219{
220 m_uplinkAllocations.clear ();
223 bool allocationForDsa = false;
224
225 uint32_t symbolsToAllocation = 0;
226 uint32_t allocationSize = 0; // size in symbols
227 uint32_t availableSymbols = GetBs ()->GetNrUlSymbols ();
228
229 AllocateInitialRangingInterval (symbolsToAllocation, availableSymbols);
230
231 std::vector<SSRecord*> *ssRecords = GetBs ()->GetSSManager ()->GetSSRecords ();
232 for (std::vector<SSRecord*>::iterator iter = ssRecords->begin (); iter != ssRecords->end (); ++iter)
233 {
234 SSRecord *ssRecord = *iter;
235
236 if (ssRecord->GetIsBroadcastSS ())
237 {
238 continue;
239 }
240 Cid cid = ssRecord->GetBasicCid ();
241 OfdmUlMapIe ulMapIe;
242 ulMapIe.SetCid (cid);
243
245 {
246 // SS's ranging is not yet complete
247 // allocating invited initial ranging interval
249 allocationSize = GetBs ()->GetRangReqOppSize ();
251
252 if (availableSymbols >= allocationSize)
253 {
254 AddUplinkAllocation (ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
255 }
256 else
257 {
258 break;
259 }
260 }
261 else
262 {
263 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType ();
264
265 // need to update because modulation/FEC to UIUC mapping may vary over time
266 ulMapIe.SetUiuc (GetBs ()->GetBurstProfileManager ()->GetBurstProfile (modulationType,
268
269 // establish service flows for SS
271 && !ssRecord->GetAreServiceFlowsAllocated ())
272 {
273
274 // allocating grant (with arbitrary size) to allow SS to send DSA messages DSA-REQ and DSA-ACK
275 // only one DSA allocation per frame
276 if (!allocationForDsa)
277 {
278 allocationSize = GetBs ()->GetPhy ()->GetNrSymbols (sizeof(DsaReq), modulationType);
279
280 if (availableSymbols >= allocationSize)
281 {
282 AddUplinkAllocation (ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
283 allocationForDsa = true;
284 }
285 else
286 {
287 break;
288 }
289 }
290 }
291 else
292 {
293 // all service flows associated to SS are established now
294
295 /* Implementation of uplink scheduler
296 * [1] Freitag, J.; da Fonseca, N.L.S., "Uplink Scheduling with Quality of Service in IEEE 802.16 Networks,"
297 * Global Telecommunications Conference, 2007. GLOBECOM '07. IEEE , vol., no., pp.2503-2508, 26-30 Nov. 2007
298 * URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=4411386&isnumber=4410910 */
299
300 // Step 1
301 if (availableSymbols)
302 {
303 /*allocating grants for data transmission for UGS flows (Data Grant Burst Type IEs, 6.3.7.4.3.3)
304 (grant has been referred by different names e.g. transmission opportunity, slot, uplink allocation, etc)*/
305 if (ssRecord->GetHasServiceFlowUgs ())
306 {
307 NS_LOG_DEBUG ("At " << Simulator::Now ().As (Time::S) << " offering be unicast polling");
308 // Recover period interval information for UGS flow
309 Time frame_duration = GetBs ()->GetPhy ()->GetFrameDuration ();
310 Time
311 timestamp =
312 (*(ssRecord->GetServiceFlows (ServiceFlow::SF_TYPE_UGS).begin ()))->GetRecord ()->GetLastGrantTime ()
313 + MilliSeconds ((*(ssRecord->GetServiceFlows (ServiceFlow::SF_TYPE_UGS).begin ()))->GetUnsolicitedGrantInterval ());
314
315 int64_t frame = ((timestamp - Simulator::Now ()) / frame_duration).GetHigh ();
316
317 if (frame <= 1)
318 {
319 // UGS Grants
320 // It is not necessary to enqueue UGS grants once it is periodically served
321 ServiceUnsolicitedGrants (ssRecord,
323 ulMapIe,
324 modulationType,
325 symbolsToAllocation,
326 availableSymbols);
327 }
328 }
329
330 // enqueue allocate unicast polls for rtPS flows if bandwidth is available
331 if (ssRecord->GetHasServiceFlowRtps ())
332 {
333 NS_LOG_DEBUG ("At " << Simulator::Now ().As (Time::S) << " offering rtps unicast polling");
335 EnqueueJob (UlJob::HIGH, jobRTPSPoll);
336 }
337
338 if (ssRecord->GetHasServiceFlowNrtps ())
339 {
340 NS_LOG_DEBUG ("At " << Simulator::Now ().As (Time::S) << " offering nrtps unicast polling");
341 // allocate unicast polls for nrtPS flows if bandwidth is available
343 EnqueueJob (UlJob::HIGH, jobNRTPSPoll);
344 }
345
346 if (ssRecord->GetHasServiceFlowBe ())
347 {
348 NS_LOG_DEBUG ("At " << Simulator::Now ().As (Time::S) << " offering be unicast polling");
349 // finally allocate unicast polls for BE flows if bandwidth is available
351 EnqueueJob (UlJob::HIGH, jobBEPoll);
352 }
353 }
354 }
355 }
356 }
357 NS_LOG_DEBUG ("At " << Simulator::Now ().As (Time::S)<< " high queue has " << m_uplinkJobs_high.size ()<< " jobs - after sched");
358
359 uint32_t availableSymbolsAux = availableSymbols;
360 uint32_t symbolsUsed = 0;
361
362 symbolsUsed += CountSymbolsQueue (m_uplinkJobs_high);
363 availableSymbolsAux -= symbolsUsed;
364
365 // Step 2 - Check Deadline - Migrate requests with deadline expiring
366 CheckDeadline (availableSymbolsAux);
367
368 // Step 3 - Check Minimum Bandwidth
369 CheckMinimumBandwidth (availableSymbolsAux);
370
371 // Scheduling high priority queue
372 NS_LOG_DEBUG ("At " << Simulator::Now ().As (Time::S)<< " high queue has " << m_uplinkJobs_high.size ()<< " jobs");
373 while ((availableSymbols) && (!m_uplinkJobs_high.empty ()))
374 {
375
376 Ptr<UlJob> job = m_uplinkJobs_high.front ();
377 OfdmUlMapIe ulMapIe;
378 SSRecord * ssRecord = job->GetSsRecord ();
379 enum ServiceFlow::SchedulingType schedulingType = job->GetSchedulingType ();
380
381 Cid cid = ssRecord->GetBasicCid ();
382 ulMapIe.SetCid (cid);
383 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType ();
384 // need to update because modulation/FEC to UIUC mapping may vary over time
385 ulMapIe.SetUiuc (GetBs ()->GetBurstProfileManager ()->GetBurstProfile (modulationType,
387
388 ReqType reqType = job->GetType ();
389
390 if (reqType == UNICAST_POLLING)
391 {
392 ServiceUnsolicitedGrants (ssRecord,
393 schedulingType,
394 ulMapIe,
395 modulationType,
396 symbolsToAllocation,
397 availableSymbols);
398 }
399 else if (reqType == DATA)
400 {
401 ServiceFlow *serviceFlow = job->GetServiceFlow ();
402 uint32_t allocSizeBytes = job->GetSize ();
404 schedulingType,
405 ulMapIe,
406 modulationType,
407 symbolsToAllocation,
408 availableSymbols,
409 allocSizeBytes);
410 }
411 m_uplinkJobs_high.pop_front ();
412 }
413
414 NS_LOG_DEBUG ("At " << Simulator::Now ().As (Time::S)<< " interqueue has " << m_uplinkJobs_inter.size ()<< " jobs");
415 /* Scheduling intermediate priority queue */
416 while ((availableSymbols) && (!m_uplinkJobs_inter.empty ()))
417 {
418 NS_LOG_DEBUG ("At " << Simulator::Now ().As (Time::S)<< " Scheduling interqueue");
419 Ptr<UlJob> job = m_uplinkJobs_inter.front ();
420 OfdmUlMapIe ulMapIe;
421 SSRecord * ssRecord = job->GetSsRecord ();
422 enum ServiceFlow::SchedulingType schedulingType = job->GetSchedulingType ();
423
424 Cid cid = ssRecord->GetBasicCid ();
425 ulMapIe.SetCid (cid);
426 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType ();
427 // need to update because modulation/FEC to UIUC mapping may vary over time
428 ulMapIe.SetUiuc (GetBs ()->GetBurstProfileManager ()->GetBurstProfile (modulationType,
430
431 ReqType reqType = job->GetType ();
432
433 if (reqType == DATA)
434 {
435 ServiceBandwidthRequests (ssRecord,
436 schedulingType,
437 ulMapIe,
438 modulationType,
439 symbolsToAllocation,
440 availableSymbols);
441 }
442 else
443 {
444 NS_FATAL_ERROR ("Intermediate priority queue only should enqueue data packets.");
445 }
446 m_uplinkJobs_inter.pop_front ();
447 }
448
449 /* Scheduling low priority queue */
450 while ((availableSymbols) && (!m_uplinkJobs_low.empty ()))
451 {
452
453 Ptr<UlJob> job = m_uplinkJobs_low.front ();
454 OfdmUlMapIe ulMapIe;
455 SSRecord * ssRecord = job->GetSsRecord ();
456 enum ServiceFlow::SchedulingType schedulingType = job->GetSchedulingType ();
457
458 Cid cid = ssRecord->GetBasicCid ();
459 ulMapIe.SetCid (cid);
460 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType ();
461 // need to update because modulation/FEC to UIUC mapping may vary over time
462 ulMapIe.SetUiuc (GetBs ()->GetBurstProfileManager ()->GetBurstProfile (modulationType,
464
465 ReqType reqType = job->GetType ();
466
467 if (reqType == DATA)
468 {
469 ServiceBandwidthRequests (ssRecord,
470 schedulingType,
471 ulMapIe,
472 modulationType,
473 symbolsToAllocation,
474 availableSymbols);
475 }
476 else
477 {
478 NS_FATAL_ERROR ("Low priority queue only should enqueue data packets.");
479 }
480 m_uplinkJobs_low.pop_front ();
481 }
482
483 OfdmUlMapIe ulMapIeEnd;
484 ulMapIeEnd.SetCid (Cid (0));
485 ulMapIeEnd.SetStartTime (symbolsToAllocation);
487 ulMapIeEnd.SetDuration (0);
488 m_uplinkAllocations.push_back (ulMapIeEnd);
489
490 // setting DL/UL subframe allocation for the next frame
491 GetBs ()->GetBandwidthManager ()->SetSubframeRatio ();
492}
493
495 enum ServiceFlow::SchedulingType schedulingType, OfdmUlMapIe &ulMapIe,
496 const WimaxPhy::ModulationType modulationType,
497 uint32_t &symbolsToAllocation, uint32_t &availableSymbols, uint32_t allocationSizeBytes)
498{
499 uint32_t allocSizeBytes = allocationSizeBytes;
500 uint32_t allocSizeSymbols = 0;
501
502 ServiceFlowRecord *record = serviceFlow->GetRecord ();
503
504 uint32_t requiredBandwidth = record->GetRequestedBandwidth ();
505
506 if (requiredBandwidth > 0)
507 {
508 allocSizeSymbols = GetBs ()->GetPhy ()->GetNrSymbols (allocSizeBytes, modulationType);
509
510 if (availableSymbols < allocSizeSymbols)
511 {
512 allocSizeSymbols = availableSymbols;
513 }
514
515 if (availableSymbols >= allocSizeSymbols)
516 {
518 "At " << Simulator::Now ().As (Time::S)<<" BS uplink scheduler, "
519 << serviceFlow->GetSchedulingTypeStr ()
520 << " allocation, size: " << allocSizeSymbols << " symbols"
521 << ", CID: "
522 << serviceFlow->GetConnection ()->GetCid ()
523 << ", SFID: " << serviceFlow->GetSfid ()
524 << ", bw requested: " << record->GetRequestedBandwidth ()
525 << ", bw granted: " << allocSizeBytes
526 << std::endl);
527
528 record->UpdateGrantedBandwidthTemp (allocSizeBytes);
529 record->UpdateGrantedBandwidth (allocSizeBytes);
530 record->UpdateRequestedBandwidth (-allocSizeBytes);
531
532 record->UpdateBwSinceLastExpiry (allocSizeBytes);
533
534
535 AddUplinkAllocation (ulMapIe, allocSizeSymbols, symbolsToAllocation,
536 availableSymbols);
537 } else
538 {
539 return false;
540 }
541 }
542 return true;
543}
544
547{
548 uint32_t symbols = 0;
549 for (std::list<Ptr<UlJob> >::iterator iter = jobs.begin (); iter != jobs.end (); ++iter)
550 {
551 Ptr<UlJob> job = *iter;
552
553 // count symbols
554 symbols += CountSymbolsJobs (job);
555 }
556 return symbols;
557}
558
561{
562 Ptr<UlJob> job = CreateObject <UlJob> ();
563 job->SetSsRecord (ssRecord);
564 job->SetSchedulingType (schedType);
565 job->SetServiceFlow (*(ssRecord->GetServiceFlows (schedType).begin ()));
566 job->SetType (reqType);
567 return job;
568}
569
572{
573 SSRecord *ssRecord = job->GetSsRecord ();
574 ServiceFlow *serviceFlow = job->GetServiceFlow ();
575 uint32_t allocationSize = 0;
576
577 if (job->GetType () == UNICAST_POLLING)
578 {
579 // if polling
580 Time currentTime = Simulator::Now ();
581 allocationSize = 0;
582 if ((currentTime - serviceFlow->GetRecord ()->GetGrantTimeStamp ()).GetMilliSeconds ()
583 >= serviceFlow->GetUnsolicitedPollingInterval ())
584 {
585 allocationSize = GetBs ()->GetBwReqOppSize ();
586 }
587 }
588 else
589 {
590 // if data
591 uint16_t sduSize = serviceFlow->GetSduSize ();
592 ServiceFlowRecord *record = serviceFlow->GetRecord ();
593 uint32_t requiredBandwidth = record->GetRequestedBandwidth () - record->GetGrantedBandwidth ();
594 if (requiredBandwidth > 0)
595 {
596 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType ();
597 if (sduSize > 0)
598 {
599 // if SDU size is mentioned, allocate grant of that size
600 allocationSize = GetBs ()->GetPhy ()->GetNrSymbols (sduSize, modulationType);
601 }
602 else
603 {
604 allocationSize = GetBs ()->GetPhy ()->GetNrSymbols (requiredBandwidth, modulationType);
605 }
606 }
607 }
608 return allocationSize;
609}
610
611void
613{
614 switch (priority)
615 {
616 case UlJob::HIGH:
617 m_uplinkJobs_high.push_back (job);
618 break;
620 m_uplinkJobs_inter.push_back (job);
621 break;
622 case UlJob::LOW:
623 m_uplinkJobs_low.push_back (job);
624 }
625}
626
629{
630 Ptr<UlJob> job_front;
631 switch (priority)
632 {
633 case UlJob::HIGH:
634 job_front = m_uplinkJobs_high.front ();
635 m_uplinkJobs_high.pop_front ();
636 break;
638 job_front = m_uplinkJobs_inter.front ();
639 m_uplinkJobs_inter.pop_front ();
640 break;
641 case UlJob::LOW:
642 job_front = m_uplinkJobs_low.front ();
643 m_uplinkJobs_low.pop_front ();
644 }
645 return job_front;
646}
647
648void
650{
651 // for each request in the imermediate queue
652 if (m_uplinkJobs_inter.size () > 0)
653 {
654 std::list<Ptr<UlJob> >::iterator iter = m_uplinkJobs_inter.begin ();
655
656 while (iter != m_uplinkJobs_inter.end () && availableSymbols)
657 {
658 Ptr<UlJob> job = *iter;
659
660 // guarantee delay bound for rtps connections
661 if (job->GetSchedulingType () == ServiceFlow::SF_TYPE_RTPS)
662 {
663 Time deadline = job->GetDeadline ();
664 Time frame_duration = GetBs ()->GetPhy ()->GetFrameDuration ();
665
666 int64_t frame = ((deadline - Simulator::Now ()) / frame_duration).GetHigh ();
667
668 NS_LOG_DEBUG ("At " << Simulator::Now ().As (Time::S) << " reserved traffic rate: "
669 << job->GetServiceFlow ()->GetMinReservedTrafficRate ()
670 <<" deadline: "<<job->GetDeadline ().As (Time::S) << " frame start: "<<GetBs ()->m_frameStartTime.As (Time::S)
671 <<" frame duration: "<< frame_duration );
672
673 // should be schedule in this frame to max latency
674 if (frame >= 3)
675 {
676
677 if (availableSymbols)
678 {
679 uint32_t availableBytes = GetBs ()->GetPhy ()->GetNrBytes (availableSymbols,job->GetSsRecord ()->GetModulationType ());
680 uint32_t allocationSize = job->GetSize ();
681 if (allocationSize > availableBytes)
682 {
683 allocationSize = availableBytes;
684 }
685
686
687 if (allocationSize == 0)
688 {
689 continue;
690 }
691
692 uint32_t symbolsToAllocate = GetBs ()->GetPhy ()->GetNrSymbols (allocationSize, job->GetSsRecord ()->GetModulationType ());
693 if (symbolsToAllocate > availableSymbols)
694 {
695 symbolsToAllocate = availableSymbols;
696 allocationSize = GetBs ()->GetPhy ()->GetNrBytes (symbolsToAllocate,job->GetSsRecord ()->GetModulationType ());
697 }
698
699 job->SetSize (job->GetSize () - allocationSize);
700
701 Ptr<UlJob> newJob = CreateObject<UlJob> ();
702 // Record data in job
703 newJob->SetSsRecord (job->GetSsRecord ());
704 newJob->SetServiceFlow (job->GetServiceFlow ());
705 newJob->SetSize (allocationSize);
706 newJob->SetDeadline (job->GetDeadline ());
707 newJob->SetReleaseTime (job->GetReleaseTime ());
708 newJob->SetSchedulingType (job->GetSchedulingType ());
709 newJob->SetPeriod (job->GetPeriod ());
710 newJob->SetType (job->GetType ());
711
712 EnqueueJob (UlJob::HIGH, newJob);
713
714 // migrate request
715 iter++;
716 if ((job->GetSize () - allocationSize) == 0)
717 {
718 m_uplinkJobs_inter.remove (job);
719 }
720
721 }
722 }
723 else
724 {
725 iter++;
726 }
727 }
728 else
729 {
730 iter++;
731 }
732 }
733 }
734}
735
736void
738{
739 std::list<Ptr<PriorityUlJob> > priorityUlJobs;
740
741 // For each connection of type rtPS or nrtPS
742 std::vector<SSRecord*> *ssRecords = GetBs ()->GetSSManager ()->GetSSRecords ();
743 for (std::vector<SSRecord*>::iterator iter = ssRecords->begin (); iter != ssRecords->end (); ++iter)
744 {
745 SSRecord *ssRecord = *iter;
746 std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows (ServiceFlow::SF_TYPE_ALL);
747 for (std::vector<ServiceFlow*>::iterator iter2 = serviceFlows.begin (); iter2 != serviceFlows.end (); ++iter2)
748 {
749 ServiceFlow *serviceFlow = *iter2;
750 if (serviceFlow->GetSchedulingType () == ServiceFlow::SF_TYPE_RTPS || serviceFlow->GetSchedulingType ()
752 {
753 serviceFlow->GetRecord ()->SetBackloggedTemp (serviceFlow->GetRecord ()->GetBacklogged ());
754 serviceFlow->GetRecord ()->SetGrantedBandwidthTemp (serviceFlow->GetRecord ()->GetBwSinceLastExpiry ());
755 }
756 }
757 }
758
759 // for each request in the imermediate queue
760 for (std::list<Ptr<UlJob> >::const_iterator iter = m_uplinkJobs_inter.begin (); iter != m_uplinkJobs_inter.end (); ++iter)
761 {
762 Ptr<UlJob> job = *iter;
763 // SSRecord ssRecord = job->GetSsRecord();
764 ServiceFlow *serviceFlow = job->GetServiceFlow ();
765 if ((job->GetSchedulingType () == ServiceFlow::SF_TYPE_RTPS || job->GetSchedulingType ()
766 == ServiceFlow::SF_TYPE_NRTPS) && (serviceFlow->GetRecord ()->GetBacklogged () > 0))
767 {
768 uint32_t minReservedTrafficRate = serviceFlow->GetMinReservedTrafficRate ();
769 uint32_t grantedBandwidth = serviceFlow->GetRecord ()->GetBwSinceLastExpiry ();
770
771 Ptr<PriorityUlJob> priorityUlJob = CreateObject<PriorityUlJob> ();
772 priorityUlJob->SetUlJob (job);
773 // pri_array
774 if (minReservedTrafficRate <= grantedBandwidth)
775 {
776 priorityUlJob->SetPriority (-10000);
777 }
778 else
779 {
780 uint32_t allocationSize = serviceFlow->GetRecord ()->GetRequestedBandwidth ()
781 - serviceFlow->GetRecord ()->GetGrantedBandwidth ();
782 uint32_t sduSize = serviceFlow->GetSduSize ();
783
784 if (allocationSize > 0)
785 {
786 if (sduSize > 0)
787 {
788 // if SDU size is mentioned, grant of that size
789 allocationSize = sduSize;
790 }
791 }
792 int priority = serviceFlow->GetRecord ()->GetBackloggedTemp ()
793 - (serviceFlow->GetRecord ()->GetGrantedBandwidthTemp () - minReservedTrafficRate);
794 priorityUlJob->SetPriority (priority);
795 serviceFlow->GetRecord ()->SetGrantedBandwidthTemp (serviceFlow->GetRecord ()->GetGrantedBandwidthTemp ()
796 + allocationSize);
797 serviceFlow->GetRecord ()->SetBackloggedTemp (serviceFlow->GetRecord ()->GetBackloggedTemp ()
798 - allocationSize);
799 }
800
801 priorityUlJobs.push_back (priorityUlJob);
802 }
803 }
804
805 priorityUlJobs.sort (SortProcessPtr ());
806
807 for (std::list<Ptr<PriorityUlJob> >::const_iterator iter = priorityUlJobs.begin (); iter != priorityUlJobs.end (); ++iter)
808 {
809 Ptr<PriorityUlJob> priorityUlJob = *iter;
810 Ptr<UlJob> job_priority = priorityUlJob->GetUlJob ();
811 Ptr<UlJob> job = job_priority;
812 if (availableSymbols)
813 {
814 availableSymbols -= CountSymbolsJobs (job);
815 // migrate request
816 m_uplinkJobs_inter.remove (job);
817 EnqueueJob (UlJob::HIGH, job);
818 }
819 }
820}
821
822void
824 enum ServiceFlow::SchedulingType schedulingType,
825 OfdmUlMapIe &ulMapIe,
826 const WimaxPhy::ModulationType modulationType,
827 uint32_t &symbolsToAllocation,
828 uint32_t &availableSymbols)
829{
830 uint32_t allocationSize = 0; // size in symbols
831 uint8_t uiuc = ulMapIe.GetUiuc (); // SS's burst profile
832 std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows (schedulingType);
833
834 for (std::vector<ServiceFlow*>::iterator iter = serviceFlows.begin (); iter != serviceFlows.end (); ++iter)
835 {
836 ServiceFlow *serviceFlow = *iter;
837
838 /* in case of rtPS, nrtPS and BE, allocating unicast polls for bandwidth requests (Request IEs, 6.3.7.4.3.1).
839 in case of UGS, allocating grants for data transmission (Data Grant Burst Type IEs, 6.3.7.4.3.3) (grant has
840 been referred in this code by different names e.g. transmission opportunity, slot, allocation, etc) */
841
842 allocationSize = GetBs ()->GetBandwidthManager ()->CalculateAllocationSize (ssRecord, serviceFlow);
843
844 if (availableSymbols < allocationSize)
845 {
846 break;
847 }
848
849 if (allocationSize > 0)
850 {
851 ulMapIe.SetStartTime (symbolsToAllocation);
852 if (serviceFlow->GetSchedulingType () != ServiceFlow::SF_TYPE_UGS)
853 {
854 // special burst profile with most robust modulation type is used for unicast polls (Request IEs)
856 }
857 }
858 else
859 {
860 continue;
861 }
862
863 if (serviceFlow->GetSchedulingType () == ServiceFlow::SF_TYPE_UGS)
864 {
865 NS_LOG_DEBUG ("BS uplink scheduler, UGS allocation, size: " << allocationSize << " symbols");
866 }
867 else
868 {
869 NS_LOG_DEBUG ("BS uplink scheduler, " << serviceFlow->GetSchedulingTypeStr () << " unicast poll, size: "
870 << allocationSize << " symbols" << ", modulation: BPSK 1/2");
871 }
872
873 NS_LOG_DEBUG (", CID: " << serviceFlow->GetConnection ()->GetCid () << ", SFID: " << serviceFlow->GetSfid ());
874
875 serviceFlow->GetRecord ()->SetLastGrantTime (Simulator::Now ());
876 AddUplinkAllocation (ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
877 ulMapIe.SetUiuc (uiuc);
878 }
879}
880
881void
883 enum ServiceFlow::SchedulingType schedulingType,
884 OfdmUlMapIe &ulMapIe,
885 const WimaxPhy::ModulationType modulationType,
886 uint32_t &symbolsToAllocation,
887 uint32_t &availableSymbols)
888{
889 std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows (schedulingType);
890
891 for (std::vector<ServiceFlow*>::iterator iter = serviceFlows.begin (); iter != serviceFlows.end (); ++iter)
892 {
893 if (!ServiceBandwidthRequests (*iter,
894 schedulingType,
895 ulMapIe,
896 modulationType,
897 symbolsToAllocation,
898 availableSymbols))
899 {
900 break;
901 }
902 }
903}
904
905bool
907 enum ServiceFlow::SchedulingType schedulingType,
908 OfdmUlMapIe &ulMapIe,
909 const WimaxPhy::ModulationType modulationType,
910 uint32_t &symbolsToAllocation,
911 uint32_t &availableSymbols)
912{
913 uint32_t allocSizeBytes = 0;
914 uint32_t allocSizeSymbols = 0;
915 uint16_t sduSize = 0;
916
917 ServiceFlowRecord *record = serviceFlow->GetRecord ();
918 sduSize = serviceFlow->GetSduSize ();
919
920 uint32_t requiredBandwidth = record->GetRequestedBandwidth () - record->GetGrantedBandwidth ();
921 if (requiredBandwidth > 0)
922 {
923 if (sduSize > 0)
924 {
925 // if SDU size is mentioned, allocate grant of that size
926 allocSizeBytes = sduSize;
927 allocSizeSymbols = GetBs ()->GetPhy ()->GetNrSymbols (sduSize, modulationType);
928
929 }
930 else
931 {
932 allocSizeBytes = requiredBandwidth;
933 allocSizeSymbols = GetBs ()->GetPhy ()->GetNrSymbols (requiredBandwidth, modulationType);
934 }
935
936 if (availableSymbols >= allocSizeSymbols)
937 {
938 NS_LOG_DEBUG ("BS uplink scheduler, " << serviceFlow->GetSchedulingTypeStr () << " allocation, size: "
939 << allocSizeSymbols << " symbols" << ", CID: " << serviceFlow->GetConnection ()->GetCid () << ", SFID: "
940 << serviceFlow->GetSfid () << ", bw requested: " << record->GetRequestedBandwidth () << ", bw granted: "
941 << record->GetGrantedBandwidth ());
942
943 record->UpdateGrantedBandwidth (allocSizeBytes);
944
945 record->SetBwSinceLastExpiry (allocSizeBytes);
946
947 if (serviceFlow->GetRecord ()->GetBacklogged () < allocSizeBytes)
948 {
949 serviceFlow->GetRecord ()->SetBacklogged (0);
950 }
951 else
952 {
953 serviceFlow->GetRecord ()->IncreaseBacklogged (-allocSizeBytes);
954 }
955 serviceFlow->GetRecord ()->SetLastGrantTime (Simulator::Now ());
956
957 AddUplinkAllocation (ulMapIe, allocSizeSymbols, symbolsToAllocation, availableSymbols);
958 }
959 else
960 {
961 return false;
962 }
963 }
964 return true;
965}
966
967void
969{
970 Time ssUlStartTime = Seconds (CalculateAllocationStartTime () * GetBs ()->GetPsDuration ().GetSeconds ());
971 SetNrIrOppsAllocated (GetBs ()->GetLinkManager ()->CalculateRangingOppsToAllocate ());
972 uint32_t allocationSize = GetNrIrOppsAllocated () * GetBs ()->GetRangReqOppSize ();
973 Time timeSinceLastIrInterval = Simulator::Now () - GetTimeStampIrInterval ();
974
975 // adding one frame because may be the time has not elapsed now but will elapse before the next frame is sent
976 if (timeSinceLastIrInterval + GetBs ()->GetPhy ()->GetFrameDuration () > GetBs ()->GetInitialRangingInterval ()
977 && availableSymbols >= allocationSize)
978 {
980 OfdmUlMapIe ulMapIeIr;
981 ulMapIeIr.SetCid ((GetBs ()->GetBroadcastConnection ())->GetCid ());
982 ulMapIeIr.SetStartTime (symbolsToAllocation);
984
985 NS_LOG_DEBUG ("BS uplink scheduler, initial ranging allocation, size: " << allocationSize << " symbols"
986 << ", modulation: BPSK 1/2" );
987
988 // marking start and end of each TO, only for debugging
989 for (uint8_t i = 0; i < GetNrIrOppsAllocated (); i++)
990 {
991 GetBs ()->MarkRangingOppStart (ssUlStartTime + Seconds (symbolsToAllocation
992 * GetBs ()->GetSymbolDuration ().GetSeconds ()) + Seconds (i * GetBs ()->GetRangReqOppSize ()
993 * GetBs ()->GetSymbolDuration ().GetSeconds ()));
994 }
995
996 AddUplinkAllocation (ulMapIeIr, allocationSize, symbolsToAllocation, availableSymbols);
998 }
999}
1000
1001void
1003{
1004 uint8_t delayNrFrames = 1;
1005 uint32_t bitsPerSecond = serviceFlow->GetMinReservedTrafficRate ();
1006 WimaxPhy::ModulationType modulation;
1007 uint32_t bytesPerFrame =
1008 (uint32_t ((double)(bitsPerSecond) * GetBs ()->GetPhy ()->GetFrameDuration ().GetSeconds ())) / 8;
1009 uint32_t frameDurationMSec = GetBs ()->GetPhy ()->GetFrameDuration ().GetMilliSeconds ();
1010
1011 switch (serviceFlow->GetSchedulingType ())
1012 {
1014 {
1015 if (serviceFlow->GetIsMulticast () == true)
1016 {
1017 modulation = serviceFlow->GetModulation ();
1018 }
1019 else
1020 {
1021 modulation = ssRecord->GetModulationType ();
1022 }
1023 uint32_t grantSize = GetBs ()->GetPhy ()->GetNrSymbols (bytesPerFrame, modulation);
1024 serviceFlow->GetRecord ()->SetGrantSize (grantSize);
1025
1026 uint32_t toleratedJitter = serviceFlow->GetToleratedJitter ();
1027
1028 if (toleratedJitter > frameDurationMSec)
1029 {
1030 delayNrFrames = (uint8_t)(toleratedJitter / frameDurationMSec);
1031 }
1032
1033 uint16_t interval = delayNrFrames * frameDurationMSec;
1034 serviceFlow->SetUnsolicitedGrantInterval (interval);
1035 }
1036 break;
1038 {
1039 serviceFlow->SetUnsolicitedPollingInterval (20);
1040 }
1041 break;
1043 {
1044 // no real-time guarantees are given to NRTPS, serviced based on available bandwidth
1045 uint16_t interval = 1000;
1046 serviceFlow->SetUnsolicitedPollingInterval (interval);
1047 }
1048 break;
1050 {
1051 // no real-time guarantees are given to BE, serviced based on available bandwidth
1052 }
1053 break;
1054 default:
1055 NS_FATAL_ERROR ("Invalid scheduling type");
1056 }
1057}
1058
1060{
1061 uint32_t size = 0;
1062 std::list<Ptr <PriorityUlJob> > priorityUlJobs;
1063
1064 // for each request in the imermediate queue
1065 for (std::list<Ptr<UlJob> >::const_iterator iter = m_uplinkJobs_inter.begin (); iter
1066 != m_uplinkJobs_inter.end (); ++iter)
1067 {
1068 Ptr<UlJob> job = *iter;
1069
1070 ServiceFlow *serviceFlowJob = job->GetServiceFlow ();
1071
1072 if (serviceFlowJob == serviceFlow)
1073 {
1074 size += job->GetSize ();
1075 }
1076 }
1077 return size;
1078}
1079
1080void
1082{
1083 // Enqueue requests for uplink scheduler.
1084 Ptr<UlJob> job = CreateObject <UlJob> ();
1085 Ptr<WimaxConnection> connection = GetBs ()->GetConnectionManager ()->GetConnection (bwRequestHdr.GetCid ());
1086 SSRecord *ssRecord = GetBs ()->GetSSManager ()->GetSSRecord (connection->GetCid ());
1087 ServiceFlow *serviceFlow = connection->GetServiceFlow ();
1088
1089 uint32_t size = bwRequestHdr.GetBr ();
1090 uint32_t pendingSize = GetPendingSize (serviceFlow);
1091
1092 if (size > pendingSize)
1093 {
1094 size -= pendingSize;
1095 }
1096 else
1097 {
1098 size = 0;
1099 }
1100
1101 if (size == 0)
1102 {
1103 return;
1104 }
1105
1106
1107 Time deadline = DetermineDeadline (serviceFlow);
1108 Time currentTime = Simulator::Now ();
1109 Time period = deadline; // So that deadline is properly updated..
1110
1111 NS_LOG_DEBUG ("At "<<Simulator::Now ().As (Time::S)<<" at BS uplink scheduler, processing bandwidth request from." <<
1112 ssRecord->GetMacAddress () << " and sf " << serviceFlow->GetSchedulingType () <<" with deadline in " << deadline.As (Time::S) << " and size " << size << " aggreg size " << bwRequestHdr.GetBr ());
1113
1114 // Record data in job
1115 job->SetSsRecord (ssRecord);
1116 job->SetServiceFlow (serviceFlow);
1117 job->SetSize (size);
1118 job->SetDeadline (deadline);
1119 job->SetReleaseTime (currentTime);
1120 job->SetSchedulingType (serviceFlow->GetSchedulingType ());
1121 job->SetPeriod (period);
1122 job->SetType (DATA);
1123
1124 // Enqueue job in Uplink Scheduler
1125 switch (serviceFlow->GetSchedulingType ())
1126 {
1129 break;
1132 break;
1134 EnqueueJob (UlJob::LOW, job);
1135 break;
1136 default:
1137 EnqueueJob (UlJob::LOW, job);
1138 break;
1139 }
1140}
1141
1142/*
1143 * Calculate Deadline of requests according to QoS parameter
1144 * */
1145Time
1147{
1148 uint32_t latency = serviceFlow->GetMaximumLatency ();
1149 Time lastGrantTime = serviceFlow->GetRecord ()->GetLastGrantTime ();
1150 Time deadline = MilliSeconds (latency) + lastGrantTime;
1151 return deadline;
1152}
1153
1154void
1156{
1157 // virtual function on UplinkScheduler
1158 // this is not necessary on this implementation
1159}
1160
1161} // namespace ns3
This class implements the bandwidth-request mac Header as described by IEEE Standard for Local and me...
Cid GetCid(void) const
Get CID field.
uint32_t GetBr(void) const
Get BR field.
Cid class.
Definition: cid.h:38
This class implements the DSA-REQ message described by "IEEE Standard for Local and metropolitan area...
Definition: mac-messages.h:374
This class implements the UL-MAP_IE message as described by "IEEE Standard for Local and metropolitan...
uint8_t GetUiuc(void) const
Get UIUC.
void SetStartTime(uint16_t startTime)
Set start time.
void SetDuration(uint16_t duration)
Set duration.
void SetCid(const Cid &cid)
Set CID.
void SetUiuc(uint8_t uiuc)
Set UIUC.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
This class is used by the base station to store some information related to subscriber station in the...
Definition: ss-record.h:44
bool GetHasServiceFlowBe(void) const
Check if at least one flow has scheduling type SF_TYPE_BE.
Definition: ss-record.cc:294
bool GetHasServiceFlowNrtps(void) const
Check if at least one flow has scheduling type SF_TYPE_NRTPS.
Definition: ss-record.cc:281
bool GetPollForRanging(void) const
Get poll for ranging.
Definition: ss-record.cc:194
WimaxNetDevice::RangingStatus GetRangingStatus(void) const
Get ranging status.
Definition: ss-record.cc:176
WimaxPhy::ModulationType GetModulationType(void) const
Get modulation type.
Definition: ss-record.cc:164
std::vector< ServiceFlow * > GetServiceFlows(enum ServiceFlow::SchedulingType schedulingType) const
Get service flows.
Definition: ss-record.cc:229
bool GetHasServiceFlowRtps(void) const
Check if at least one flow has scheduling type SF_TYPE_RTPS.
Definition: ss-record.cc:268
Mac48Address GetMacAddress(void) const
Get MAC address.
Definition: ss-record.cc:116
bool GetAreServiceFlowsAllocated(void) const
Check if service flows are allocated.
Definition: ss-record.cc:206
bool GetHasServiceFlowUgs(void) const
Check if at least one flow has scheduling type SF_TYPE_UGS.
Definition: ss-record.cc:255
bool GetIsBroadcastSS(void)
Get is broadcast SS.
Definition: ss-record.cc:249
Cid GetBasicCid(void) const
Get basic CID.
Definition: ss-record.cc:92
This class implements service flows as described by the IEEE-802.16 standard.
Definition: service-flow.h:40
enum WimaxPhy::ModulationType GetModulation(void) const
Get modulation.
uint32_t GetMinReservedTrafficRate(void) const
Get minimum reserved traffic rate.
uint8_t GetSduSize(void) const
Get SDU size.
uint16_t GetUnsolicitedPollingInterval(void) const
Get unsolicited polling interval.
enum ServiceFlow::SchedulingType GetSchedulingType(void) const
Get scheduling type.
SchedulingType
section 11.13.11 Service flow scheduling type, page 701
Definition: service-flow.h:59
char * GetSchedulingTypeStr(void) const
Get scheduling type string.
ServiceFlowRecord * GetRecord(void) const
Get service flow record.
Ptr< WimaxConnection > GetConnection(void) const
Can return a null connection is this service flow has not been associated yet to a connection.
uint32_t GetMaximumLatency(void) const
Get maximum latency.
void SetUnsolicitedGrantInterval(uint16_t unsolicitedGrantInterval)
Set unsolicied grant interval.
bool GetIsMulticast(void) const
Get is multicast.
void SetUnsolicitedPollingInterval(uint16_t unsolicitedPollingInterval)
Set unsolicited polling interval.
uint32_t GetToleratedJitter(void) const
Get tolerated jitter.
uint32_t GetSfid(void) const
Get SFID.
this class implements a structure to manage some parameters and statistics related to a service flow
Time GetGrantTimeStamp(void) const
void UpdateRequestedBandwidth(uint32_t requestedBandwidth)
update the requested bandwidth
uint32_t GetGrantedBandwidthTemp(void)
void UpdateGrantedBandwidthTemp(uint32_t grantedBandwidthTemp)
update the temporary granted bandwidth
uint32_t GetRequestedBandwidth(void)
void IncreaseBacklogged(uint32_t backlogged)
increase backlogged
uint32_t GetBacklogged(void) const
void SetBackloggedTemp(uint32_t backloggedTemp)
set temporary back logged
uint32_t GetBwSinceLastExpiry(void)
void SetGrantSize(uint32_t grantSize)
Set the grant size (only for UGS service flows)
void SetGrantedBandwidthTemp(uint32_t grantedBandwidthTemp)
set the temporary granted bandwidth
void SetBwSinceLastExpiry(uint32_t bwSinceLastExpiry)
set BW since last expiry
void UpdateGrantedBandwidth(uint32_t grantedBandwidth)
update the granted bandwidth
uint32_t GetGrantedBandwidth(void)
void UpdateBwSinceLastExpiry(uint32_t bwSinceLastExpiry)
update BW since last expiry
void SetBacklogged(uint32_t backlogged)
set backlogged
void SetLastGrantTime(Time grantTime)
set last grant time
uint32_t GetBackloggedTemp(void) const
Time GetLastGrantTime(void) const
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
@ S
second
Definition: nstime.h:114
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:432
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
JobPriority
Job priority enumeration.
Definition: ul-job.h:52
@ INTERMEDIATE
Definition: ul-job.h:54
@ HIGH
Definition: ul-job.h:55
ModulationType
ModulationType enumeration.
Definition: wimax-phy.h:52
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1309
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG(level, msg)
This macro allows you to log an arbitrary message at a specific log level.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ReqType
Request type enumeration.
Definition: ul-job.h:38
@ UNICAST_POLLING
Definition: ul-job.h:40
@ DATA
Definition: ul-job.h:39
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:536
@ LOG_DEBUG
Rare ad-hoc debug messages.
Definition: log.h:103
#define list
SortProcessPtr structure.
Definition: ul-job.h:241