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