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