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 (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
179 {
180 SSRecord* ssRecord = *iter;
181 std::vector<ServiceFlow*> serviceFlows =
183
184 // For each flow
185 for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
186 {
187 ServiceFlow* serviceFlow = *iter2;
188 if ((serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS) ||
190 {
191 min_bw = (int)ceil(serviceFlow->GetMinReservedTrafficRate());
192
193 // This way we can compensate flows which did not get min_bw in the previous window
194 if ((serviceFlow->GetRecord()->GetBacklogged() > 0) &&
195 (serviceFlow->GetRecord()->GetBwSinceLastExpiry() < min_bw))
196 {
197 serviceFlow->GetRecord()->UpdateBwSinceLastExpiry(-min_bw);
198
199 // if backlogged < granted_bw then we don't need to provide granted_bw + min_bw
200 // in next window, but backlogged + min_bw
201 if (serviceFlow->GetRecord()->GetBacklogged() <
202 (serviceFlow->GetRecord()->GetBwSinceLastExpiry()))
203 {
204 serviceFlow->GetRecord()->SetBwSinceLastExpiry(
205 -serviceFlow->GetRecord()->GetBacklogged());
206 }
207 }
208 else
209 {
210 serviceFlow->GetRecord()->SetBwSinceLastExpiry(0);
211 }
212 }
213 }
214 }
215
216 // Periodically reset window
218}
219
220void
222{
223 m_uplinkAllocations.clear();
226 bool allocationForDsa = false;
227
228 uint32_t symbolsToAllocation = 0;
229 uint32_t allocationSize = 0; // size in symbols
230 uint32_t availableSymbols = GetBs()->GetNrUlSymbols();
231
232 AllocateInitialRangingInterval(symbolsToAllocation, availableSymbols);
233
234 std::vector<SSRecord*>* ssRecords = GetBs()->GetSSManager()->GetSSRecords();
235 for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
236 {
237 SSRecord* ssRecord = *iter;
238
239 if (ssRecord->GetIsBroadcastSS())
240 {
241 continue;
242 }
243 Cid cid = ssRecord->GetBasicCid();
244 OfdmUlMapIe ulMapIe;
245 ulMapIe.SetCid(cid);
246
247 if (ssRecord->GetPollForRanging() &&
249 {
250 // SS's ranging is not yet complete
251 // allocating invited initial ranging interval
253 allocationSize = GetBs()->GetRangReqOppSize();
255
256 if (availableSymbols >= allocationSize)
257 {
258 AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
259 }
260 else
261 {
262 break;
263 }
264 }
265 else
266 {
267 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
268
269 // need to update because modulation/FEC to UIUC mapping may vary over time
270 ulMapIe.SetUiuc(GetBs()->GetBurstProfileManager()->GetBurstProfile(
271 modulationType,
273
274 // establish service flows for SS
276 !ssRecord->GetAreServiceFlowsAllocated())
277 {
278 // allocating grant (with arbitrary size) to allow SS to send DSA messages DSA-REQ
279 // and DSA-ACK only one DSA allocation per frame
280 if (!allocationForDsa)
281 {
282 allocationSize =
283 GetBs()->GetPhy()->GetNrSymbols(sizeof(DsaReq), modulationType);
284
285 if (availableSymbols >= allocationSize)
286 {
287 AddUplinkAllocation(ulMapIe,
288 allocationSize,
289 symbolsToAllocation,
290 availableSymbols);
291 allocationForDsa = true;
292 }
293 else
294 {
295 break;
296 }
297 }
298 }
299 else
300 {
301 // all service flows associated to SS are established now
302
303 /* Implementation of uplink scheduler
304 * [1] Freitag, J.; da Fonseca, N.L.S., "Uplink Scheduling with Quality of Service
305 * in IEEE 802.16 Networks," Global Telecommunications Conference, 2007. GLOBECOM
306 * '07. IEEE , vol., no., pp.2503-2508, 26-30 Nov. 2007 URL:
307 * http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=4411386&isnumber=4410910 */
308
309 // Step 1
310 if (availableSymbols)
311 {
312 /*allocating grants for data transmission for UGS flows (Data Grant Burst Type
313 IEs, 6.3.7.4.3.3) (grant has been referred by different names e.g. transmission
314 opportunity, slot, uplink allocation, etc)*/
315 if (ssRecord->GetHasServiceFlowUgs())
316 {
317 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
318 << " offering be unicast polling");
319 // Recover period interval information for UGS flow
320 Time frame_duration = GetBs()->GetPhy()->GetFrameDuration();
321 Time timestamp =
322 (*(ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_UGS).begin()))
323 ->GetRecord()
324 ->GetLastGrantTime() +
326 (*(ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_UGS).begin()))
327 ->GetUnsolicitedGrantInterval());
328
329 int64_t frame = ((timestamp - Simulator::Now()) / frame_duration).GetHigh();
330
331 if (frame <= 1)
332 {
333 // UGS Grants
334 // It is not necessary to enqueue UGS grants once it is periodically
335 // served
338 ulMapIe,
339 modulationType,
340 symbolsToAllocation,
341 availableSymbols);
342 }
343 }
344
345 // enqueue allocate unicast polls for rtPS flows if bandwidth is available
346 if (ssRecord->GetHasServiceFlowRtps())
347 {
348 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
349 << " offering rtps unicast polling");
350 Ptr<UlJob> jobRTPSPoll =
352 EnqueueJob(UlJob::HIGH, jobRTPSPoll);
353 }
354
355 if (ssRecord->GetHasServiceFlowNrtps())
356 {
357 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
358 << " offering nrtps unicast polling");
359 // allocate unicast polls for nrtPS flows if bandwidth is available
360 Ptr<UlJob> jobNRTPSPoll =
362 EnqueueJob(UlJob::HIGH, jobNRTPSPoll);
363 }
364
365 if (ssRecord->GetHasServiceFlowBe())
366 {
367 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
368 << " offering be unicast polling");
369 // finally allocate unicast polls for BE flows if bandwidth is available
370 Ptr<UlJob> jobBEPoll =
372 EnqueueJob(UlJob::HIGH, jobBEPoll);
373 }
374 }
375 }
376 }
377 }
378 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " high queue has "
379 << m_uplinkJobs_high.size() << " jobs - after sched");
380
381 uint32_t availableSymbolsAux = availableSymbols;
382 uint32_t symbolsUsed = 0;
383
384 symbolsUsed += CountSymbolsQueue(m_uplinkJobs_high);
385 availableSymbolsAux -= symbolsUsed;
386
387 // Step 2 - Check Deadline - Migrate requests with deadline expiring
388 CheckDeadline(availableSymbolsAux);
389
390 // Step 3 - Check Minimum Bandwidth
391 CheckMinimumBandwidth(availableSymbolsAux);
392
393 // Scheduling high priority queue
394 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " high queue has "
395 << m_uplinkJobs_high.size() << " jobs");
396 while ((availableSymbols) && (!m_uplinkJobs_high.empty()))
397 {
398 Ptr<UlJob> job = m_uplinkJobs_high.front();
399 OfdmUlMapIe ulMapIe;
400 SSRecord* ssRecord = job->GetSsRecord();
401 ServiceFlow::SchedulingType schedulingType = job->GetSchedulingType();
402
403 Cid cid = ssRecord->GetBasicCid();
404 ulMapIe.SetCid(cid);
405 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
406 // need to update because modulation/FEC to UIUC mapping may vary over time
407 ulMapIe.SetUiuc(
408 GetBs()->GetBurstProfileManager()->GetBurstProfile(modulationType,
410
411 ReqType reqType = job->GetType();
412
413 if (reqType == UNICAST_POLLING)
414 {
416 schedulingType,
417 ulMapIe,
418 modulationType,
419 symbolsToAllocation,
420 availableSymbols);
421 }
422 else if (reqType == DATA)
423 {
424 ServiceFlow* serviceFlow = job->GetServiceFlow();
425 uint32_t allocSizeBytes = job->GetSize();
427 schedulingType,
428 ulMapIe,
429 modulationType,
430 symbolsToAllocation,
431 availableSymbols,
432 allocSizeBytes);
433 }
434 m_uplinkJobs_high.pop_front();
435 }
436
437 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " interqueue has "
438 << m_uplinkJobs_inter.size() << " jobs");
439 /* Scheduling intermediate priority queue */
440 while ((availableSymbols) && (!m_uplinkJobs_inter.empty()))
441 {
442 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " Scheduling interqueue");
443 Ptr<UlJob> job = m_uplinkJobs_inter.front();
444 OfdmUlMapIe ulMapIe;
445 SSRecord* ssRecord = job->GetSsRecord();
446 ServiceFlow::SchedulingType schedulingType = job->GetSchedulingType();
447
448 Cid cid = ssRecord->GetBasicCid();
449 ulMapIe.SetCid(cid);
450 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
451 // need to update because modulation/FEC to UIUC mapping may vary over time
452 ulMapIe.SetUiuc(
453 GetBs()->GetBurstProfileManager()->GetBurstProfile(modulationType,
455
456 ReqType reqType = job->GetType();
457
458 if (reqType == DATA)
459 {
461 schedulingType,
462 ulMapIe,
463 modulationType,
464 symbolsToAllocation,
465 availableSymbols);
466 }
467 else
468 {
469 NS_FATAL_ERROR("Intermediate priority queue only should enqueue data packets.");
470 }
471 m_uplinkJobs_inter.pop_front();
472 }
473
474 /* Scheduling low priority queue */
475 while ((availableSymbols) && (!m_uplinkJobs_low.empty()))
476 {
477 Ptr<UlJob> job = m_uplinkJobs_low.front();
478 OfdmUlMapIe ulMapIe;
479 SSRecord* ssRecord = job->GetSsRecord();
480 ServiceFlow::SchedulingType schedulingType = job->GetSchedulingType();
481
482 Cid cid = ssRecord->GetBasicCid();
483 ulMapIe.SetCid(cid);
484 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
485 // need to update because modulation/FEC to UIUC mapping may vary over time
486 ulMapIe.SetUiuc(
487 GetBs()->GetBurstProfileManager()->GetBurstProfile(modulationType,
489
490 ReqType reqType = job->GetType();
491
492 if (reqType == DATA)
493 {
495 schedulingType,
496 ulMapIe,
497 modulationType,
498 symbolsToAllocation,
499 availableSymbols);
500 }
501 else
502 {
503 NS_FATAL_ERROR("Low priority queue only should enqueue data packets.");
504 }
505 m_uplinkJobs_low.pop_front();
506 }
507
508 OfdmUlMapIe ulMapIeEnd;
509 ulMapIeEnd.SetCid(Cid(0));
510 ulMapIeEnd.SetStartTime(symbolsToAllocation);
512 ulMapIeEnd.SetDuration(0);
513 m_uplinkAllocations.push_back(ulMapIeEnd);
514
515 // setting DL/UL subframe allocation for the next frame
516 GetBs()->GetBandwidthManager()->SetSubframeRatio();
517}
518
519bool
521 ServiceFlow::SchedulingType schedulingType,
522 OfdmUlMapIe& ulMapIe,
523 const WimaxPhy::ModulationType modulationType,
524 uint32_t& symbolsToAllocation,
525 uint32_t& availableSymbols,
526 uint32_t allocationSizeBytes)
527{
528 uint32_t allocSizeBytes = allocationSizeBytes;
529 uint32_t allocSizeSymbols = 0;
530
531 ServiceFlowRecord* record = serviceFlow->GetRecord();
532
533 uint32_t requiredBandwidth = record->GetRequestedBandwidth();
534
535 if (requiredBandwidth > 0)
536 {
537 allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(allocSizeBytes, modulationType);
538
539 if (availableSymbols < allocSizeSymbols)
540 {
541 allocSizeSymbols = availableSymbols;
542 }
543
544 if (availableSymbols >= allocSizeSymbols)
545 {
546 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " BS uplink scheduler, "
547 << serviceFlow->GetSchedulingTypeStr()
548 << " allocation, size: " << allocSizeSymbols << " symbols"
549 << ", CID: " << serviceFlow->GetConnection()->GetCid()
550 << ", SFID: " << serviceFlow->GetSfid()
551 << ", bw requested: " << record->GetRequestedBandwidth()
552 << ", bw granted: " << allocSizeBytes << std::endl);
553
554 record->UpdateGrantedBandwidthTemp(allocSizeBytes);
555 record->UpdateGrantedBandwidth(allocSizeBytes);
556 record->UpdateRequestedBandwidth(-allocSizeBytes);
557
558 record->UpdateBwSinceLastExpiry(allocSizeBytes);
559
560 AddUplinkAllocation(ulMapIe, allocSizeSymbols, symbolsToAllocation, availableSymbols);
561 }
562 else
563 {
564 return false;
565 }
566 }
567 return true;
568}
569
572{
573 uint32_t symbols = 0;
574 for (auto iter = jobs.begin(); iter != jobs.end(); ++iter)
575 {
576 Ptr<UlJob> job = *iter;
577
578 // count symbols
579 symbols += CountSymbolsJobs(job);
580 }
581 return symbols;
582}
583
587 ReqType reqType)
588{
589 Ptr<UlJob> job = CreateObject<UlJob>();
590 job->SetSsRecord(ssRecord);
591 job->SetSchedulingType(schedType);
592 job->SetServiceFlow(*(ssRecord->GetServiceFlows(schedType).begin()));
593 job->SetType(reqType);
594 return job;
595}
596
599{
600 SSRecord* ssRecord = job->GetSsRecord();
601 ServiceFlow* serviceFlow = job->GetServiceFlow();
602 uint32_t allocationSize = 0;
603
604 if (job->GetType() == UNICAST_POLLING)
605 {
606 // if polling
607 Time currentTime = Simulator::Now();
608 allocationSize = 0;
609 if ((currentTime - serviceFlow->GetRecord()->GetGrantTimeStamp()).GetMilliSeconds() >=
610 serviceFlow->GetUnsolicitedPollingInterval())
611 {
612 allocationSize = GetBs()->GetBwReqOppSize();
613 }
614 }
615 else
616 {
617 // if data
618 uint16_t sduSize = serviceFlow->GetSduSize();
619 ServiceFlowRecord* record = serviceFlow->GetRecord();
620 uint32_t requiredBandwidth =
621 record->GetRequestedBandwidth() - record->GetGrantedBandwidth();
622 if (requiredBandwidth > 0)
623 {
624 WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
625 if (sduSize > 0)
626 {
627 // if SDU size is mentioned, allocate grant of that size
628 allocationSize = GetBs()->GetPhy()->GetNrSymbols(sduSize, modulationType);
629 }
630 else
631 {
632 allocationSize = GetBs()->GetPhy()->GetNrSymbols(requiredBandwidth, modulationType);
633 }
634 }
635 }
636 return allocationSize;
637}
638
639void
641{
642 switch (priority)
643 {
644 case UlJob::HIGH:
645 m_uplinkJobs_high.push_back(job);
646 break;
648 m_uplinkJobs_inter.push_back(job);
649 break;
650 case UlJob::LOW:
651 m_uplinkJobs_low.push_back(job);
652 }
653}
654
657{
658 Ptr<UlJob> job_front;
659 switch (priority)
660 {
661 case UlJob::HIGH:
662 job_front = m_uplinkJobs_high.front();
663 m_uplinkJobs_high.pop_front();
664 break;
666 job_front = m_uplinkJobs_inter.front();
667 m_uplinkJobs_inter.pop_front();
668 break;
669 case UlJob::LOW:
670 job_front = m_uplinkJobs_low.front();
671 m_uplinkJobs_low.pop_front();
672 }
673 return job_front;
674}
675
676void
678{
679 // for each request in the intermediate queue
680 if (!m_uplinkJobs_inter.empty())
681 {
682 auto iter = m_uplinkJobs_inter.begin();
683
684 while (iter != m_uplinkJobs_inter.end() && availableSymbols)
685 {
686 Ptr<UlJob> job = *iter;
687
688 // guarantee delay bound for rtps connections
689 if (job->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS)
690 {
691 Time deadline = job->GetDeadline();
692 Time frame_duration = GetBs()->GetPhy()->GetFrameDuration();
693
694 int64_t frame = ((deadline - Simulator::Now()) / frame_duration).GetHigh();
695
696 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " reserved traffic rate: "
697 << job->GetServiceFlow()->GetMinReservedTrafficRate()
698 << " deadline: " << job->GetDeadline().As(Time::S)
699 << " frame start: " << GetBs()->m_frameStartTime.As(Time::S)
700 << " frame duration: " << frame_duration);
701
702 // should be schedule in this frame to max latency
703 if (frame >= 3)
704 {
705 if (availableSymbols)
706 {
707 uint32_t availableBytes =
708 GetBs()->GetPhy()->GetNrBytes(availableSymbols,
709 job->GetSsRecord()->GetModulationType());
710 uint32_t allocationSize = job->GetSize();
711 if (allocationSize > availableBytes)
712 {
713 allocationSize = availableBytes;
714 }
715
716 if (allocationSize == 0)
717 {
718 continue;
719 }
720
721 uint32_t symbolsToAllocate = GetBs()->GetPhy()->GetNrSymbols(
722 allocationSize,
723 job->GetSsRecord()->GetModulationType());
724 if (symbolsToAllocate > availableSymbols)
725 {
726 symbolsToAllocate = availableSymbols;
727 allocationSize = GetBs()->GetPhy()->GetNrBytes(
728 symbolsToAllocate,
729 job->GetSsRecord()->GetModulationType());
730 }
731
732 job->SetSize(job->GetSize() - allocationSize);
733
734 Ptr<UlJob> newJob = CreateObject<UlJob>();
735 // Record data in job
736 newJob->SetSsRecord(job->GetSsRecord());
737 newJob->SetServiceFlow(job->GetServiceFlow());
738 newJob->SetSize(allocationSize);
739 newJob->SetDeadline(job->GetDeadline());
740 newJob->SetReleaseTime(job->GetReleaseTime());
741 newJob->SetSchedulingType(job->GetSchedulingType());
742 newJob->SetPeriod(job->GetPeriod());
743 newJob->SetType(job->GetType());
744
745 EnqueueJob(UlJob::HIGH, newJob);
746
747 // migrate request
748 iter++;
749 if ((job->GetSize() - allocationSize) == 0)
750 {
751 m_uplinkJobs_inter.remove(job);
752 }
753 }
754 }
755 else
756 {
757 iter++;
758 }
759 }
760 else
761 {
762 iter++;
763 }
764 }
765 }
766}
767
768void
770{
771 std::list<Ptr<PriorityUlJob>> priorityUlJobs;
772
773 // For each connection of type rtPS or nrtPS
774 std::vector<SSRecord*>* ssRecords = GetBs()->GetSSManager()->GetSSRecords();
775 for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
776 {
777 SSRecord* ssRecord = *iter;
778 std::vector<ServiceFlow*> serviceFlows =
780 for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
781 {
782 ServiceFlow* serviceFlow = *iter2;
783 if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS ||
785 {
786 serviceFlow->GetRecord()->SetBackloggedTemp(
787 serviceFlow->GetRecord()->GetBacklogged());
788 serviceFlow->GetRecord()->SetGrantedBandwidthTemp(
789 serviceFlow->GetRecord()->GetBwSinceLastExpiry());
790 }
791 }
792 }
793
794 // for each request in the imermediate queue
795 for (auto iter = m_uplinkJobs_inter.begin(); iter != m_uplinkJobs_inter.end(); ++iter)
796 {
797 Ptr<UlJob> job = *iter;
798 // SSRecord ssRecord = job->GetSsRecord();
799 ServiceFlow* serviceFlow = job->GetServiceFlow();
800 if ((job->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS ||
801 job->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS) &&
802 (serviceFlow->GetRecord()->GetBacklogged() > 0))
803 {
804 uint32_t minReservedTrafficRate = serviceFlow->GetMinReservedTrafficRate();
805 uint32_t grantedBandwidth = serviceFlow->GetRecord()->GetBwSinceLastExpiry();
806
807 Ptr<PriorityUlJob> priorityUlJob = CreateObject<PriorityUlJob>();
808 priorityUlJob->SetUlJob(job);
809 // pri_array
810 if (minReservedTrafficRate <= grantedBandwidth)
811 {
812 priorityUlJob->SetPriority(-10000);
813 }
814 else
815 {
816 uint32_t allocationSize = serviceFlow->GetRecord()->GetRequestedBandwidth() -
817 serviceFlow->GetRecord()->GetGrantedBandwidth();
818 uint32_t sduSize = serviceFlow->GetSduSize();
819
820 if (allocationSize > 0)
821 {
822 if (sduSize > 0)
823 {
824 // if SDU size is mentioned, grant of that size
825 allocationSize = sduSize;
826 }
827 }
828 int priority =
829 serviceFlow->GetRecord()->GetBackloggedTemp() -
830 (serviceFlow->GetRecord()->GetGrantedBandwidthTemp() - minReservedTrafficRate);
831 priorityUlJob->SetPriority(priority);
832 serviceFlow->GetRecord()->SetGrantedBandwidthTemp(
833 serviceFlow->GetRecord()->GetGrantedBandwidthTemp() + allocationSize);
834 serviceFlow->GetRecord()->SetBackloggedTemp(
835 serviceFlow->GetRecord()->GetBackloggedTemp() - allocationSize);
836 }
837
838 priorityUlJobs.push_back(priorityUlJob);
839 }
840 }
841
842 priorityUlJobs.sort(SortProcessPtr());
843
844 for (auto iter = priorityUlJobs.begin(); iter != priorityUlJobs.end(); ++iter)
845 {
846 Ptr<PriorityUlJob> priorityUlJob = *iter;
847 Ptr<UlJob> job_priority = priorityUlJob->GetUlJob();
848 Ptr<UlJob> job = job_priority;
849 if (availableSymbols)
850 {
851 availableSymbols -= CountSymbolsJobs(job);
852 // migrate request
853 m_uplinkJobs_inter.remove(job);
855 }
856 }
857}
858
859void
861 ServiceFlow::SchedulingType schedulingType,
862 OfdmUlMapIe& ulMapIe,
863 const WimaxPhy::ModulationType modulationType,
864 uint32_t& symbolsToAllocation,
865 uint32_t& availableSymbols)
866{
867 uint32_t allocationSize = 0; // size in symbols
868 uint8_t uiuc = ulMapIe.GetUiuc(); // SS's burst profile
869 std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
870
871 for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
872 {
873 ServiceFlow* serviceFlow = *iter;
874
875 /* in case of rtPS, nrtPS and BE, allocating unicast polls for bandwidth requests (Request
876 IEs, 6.3.7.4.3.1). in case of UGS, allocating grants for data transmission (Data Grant
877 Burst Type IEs, 6.3.7.4.3.3) (grant has been referred in this code by different names e.g.
878 transmission opportunity, slot, allocation, etc) */
879
880 allocationSize =
881 GetBs()->GetBandwidthManager()->CalculateAllocationSize(ssRecord, serviceFlow);
882
883 if (availableSymbols < allocationSize)
884 {
885 break;
886 }
887
888 if (allocationSize > 0)
889 {
890 ulMapIe.SetStartTime(symbolsToAllocation);
891 if (serviceFlow->GetSchedulingType() != ServiceFlow::SF_TYPE_UGS)
892 {
893 // special burst profile with most robust modulation type is used for unicast polls
894 // (Request IEs)
896 }
897 }
898 else
899 {
900 continue;
901 }
902
903 if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_UGS)
904 {
905 NS_LOG_DEBUG("BS uplink scheduler, UGS allocation, size: " << allocationSize
906 << " symbols");
907 }
908 else
909 {
910 NS_LOG_DEBUG("BS uplink scheduler, " << serviceFlow->GetSchedulingTypeStr()
911 << " unicast poll, size: " << allocationSize
912 << " symbols"
913 << ", modulation: BPSK 1/2");
914 }
915
916 NS_LOG_DEBUG(", CID: " << serviceFlow->GetConnection()->GetCid()
917 << ", SFID: " << serviceFlow->GetSfid());
918
919 serviceFlow->GetRecord()->SetLastGrantTime(Simulator::Now());
920 AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
921 ulMapIe.SetUiuc(uiuc);
922 }
923}
924
925void
927 ServiceFlow::SchedulingType schedulingType,
928 OfdmUlMapIe& ulMapIe,
929 const WimaxPhy::ModulationType modulationType,
930 uint32_t& symbolsToAllocation,
931 uint32_t& availableSymbols)
932{
933 std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
934
935 for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
936 {
937 if (!ServiceBandwidthRequests(*iter,
938 schedulingType,
939 ulMapIe,
940 modulationType,
941 symbolsToAllocation,
942 availableSymbols))
943 {
944 break;
945 }
946 }
947}
948
949bool
951 ServiceFlow::SchedulingType schedulingType,
952 OfdmUlMapIe& ulMapIe,
953 const WimaxPhy::ModulationType modulationType,
954 uint32_t& symbolsToAllocation,
955 uint32_t& availableSymbols)
956{
957 uint32_t allocSizeBytes = 0;
958 uint32_t allocSizeSymbols = 0;
959 uint16_t sduSize = 0;
960
961 ServiceFlowRecord* record = serviceFlow->GetRecord();
962 sduSize = serviceFlow->GetSduSize();
963
964 uint32_t requiredBandwidth = record->GetRequestedBandwidth() - record->GetGrantedBandwidth();
965 if (requiredBandwidth > 0)
966 {
967 if (sduSize > 0)
968 {
969 // if SDU size is mentioned, allocate grant of that size
970 allocSizeBytes = sduSize;
971 allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(sduSize, modulationType);
972 }
973 else
974 {
975 allocSizeBytes = requiredBandwidth;
976 allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(requiredBandwidth, modulationType);
977 }
978
979 if (availableSymbols >= allocSizeSymbols)
980 {
981 NS_LOG_DEBUG("BS uplink scheduler, "
982 << serviceFlow->GetSchedulingTypeStr()
983 << " allocation, size: " << allocSizeSymbols << " symbols"
984 << ", CID: " << serviceFlow->GetConnection()->GetCid()
985 << ", SFID: " << serviceFlow->GetSfid()
986 << ", bw requested: " << record->GetRequestedBandwidth()
987 << ", bw granted: " << record->GetGrantedBandwidth());
988
989 record->UpdateGrantedBandwidth(allocSizeBytes);
990
991 record->SetBwSinceLastExpiry(allocSizeBytes);
992
993 if (serviceFlow->GetRecord()->GetBacklogged() < allocSizeBytes)
994 {
995 serviceFlow->GetRecord()->SetBacklogged(0);
996 }
997 else
998 {
999 serviceFlow->GetRecord()->IncreaseBacklogged(-allocSizeBytes);
1000 }
1001 serviceFlow->GetRecord()->SetLastGrantTime(Simulator::Now());
1002
1003 AddUplinkAllocation(ulMapIe, allocSizeSymbols, symbolsToAllocation, availableSymbols);
1004 }
1005 else
1006 {
1007 return false;
1008 }
1009 }
1010 return true;
1011}
1012
1013void
1015 uint32_t& availableSymbols)
1016{
1017 Time ssUlStartTime =
1018 Seconds(CalculateAllocationStartTime() * GetBs()->GetPsDuration().GetSeconds());
1019 SetNrIrOppsAllocated(GetBs()->GetLinkManager()->CalculateRangingOppsToAllocate());
1020 uint32_t allocationSize = GetNrIrOppsAllocated() * GetBs()->GetRangReqOppSize();
1021 Time timeSinceLastIrInterval = Simulator::Now() - GetTimeStampIrInterval();
1022
1023 // adding one frame because may be the time has not elapsed now but will elapse before the next
1024 // frame is sent
1025 if (timeSinceLastIrInterval + GetBs()->GetPhy()->GetFrameDuration() >
1026 GetBs()->GetInitialRangingInterval() &&
1027 availableSymbols >= allocationSize)
1028 {
1030 OfdmUlMapIe ulMapIeIr;
1031 ulMapIeIr.SetCid((GetBs()->GetBroadcastConnection())->GetCid());
1032 ulMapIeIr.SetStartTime(symbolsToAllocation);
1034
1035 NS_LOG_DEBUG("BS uplink scheduler, initial ranging allocation, size: "
1036 << allocationSize << " symbols"
1037 << ", modulation: BPSK 1/2");
1038
1039 // marking start and end of each TO, only for debugging
1040 for (uint8_t i = 0; i < GetNrIrOppsAllocated(); i++)
1041 {
1042 GetBs()->MarkRangingOppStart(
1043 ssUlStartTime +
1044 Seconds(symbolsToAllocation * GetBs()->GetSymbolDuration().GetSeconds()) +
1045 Seconds(i * GetBs()->GetRangReqOppSize() *
1046 GetBs()->GetSymbolDuration().GetSeconds()));
1047 }
1048
1049 AddUplinkAllocation(ulMapIeIr, allocationSize, symbolsToAllocation, availableSymbols);
1051 }
1052}
1053
1054void
1056{
1057 uint8_t delayNrFrames = 1;
1058 uint32_t bitsPerSecond = serviceFlow->GetMinReservedTrafficRate();
1059 WimaxPhy::ModulationType modulation;
1060 uint32_t bytesPerFrame =
1061 (uint32_t((double)(bitsPerSecond)*GetBs()->GetPhy()->GetFrameDuration().GetSeconds())) / 8;
1062 uint32_t frameDurationMSec = GetBs()->GetPhy()->GetFrameDuration().GetMilliSeconds();
1063
1064 switch (serviceFlow->GetSchedulingType())
1065 {
1067 if (serviceFlow->GetIsMulticast())
1068 {
1069 modulation = serviceFlow->GetModulation();
1070 }
1071 else
1072 {
1073 modulation = ssRecord->GetModulationType();
1074 }
1075 uint32_t grantSize = GetBs()->GetPhy()->GetNrSymbols(bytesPerFrame, modulation);
1076 serviceFlow->GetRecord()->SetGrantSize(grantSize);
1077
1078 uint32_t toleratedJitter = serviceFlow->GetToleratedJitter();
1079
1080 if (toleratedJitter > frameDurationMSec)
1081 {
1082 delayNrFrames = (uint8_t)(toleratedJitter / frameDurationMSec);
1083 }
1084
1085 uint16_t interval = delayNrFrames * frameDurationMSec;
1086 serviceFlow->SetUnsolicitedGrantInterval(interval);
1087 }
1088 break;
1090 serviceFlow->SetUnsolicitedPollingInterval(20);
1091 }
1092 break;
1094 // no real-time guarantees are given to NRTPS, serviced based on available bandwidth
1095 uint16_t interval = 1000;
1096 serviceFlow->SetUnsolicitedPollingInterval(interval);
1097 }
1098 break;
1100 // no real-time guarantees are given to BE, serviced based on available bandwidth
1101 }
1102 break;
1103 default:
1104 NS_FATAL_ERROR("Invalid scheduling type");
1105 }
1106}
1107
1110{
1111 uint32_t size = 0;
1112 std::list<Ptr<PriorityUlJob>> priorityUlJobs;
1113
1114 // for each request in the imermediate queue
1115 for (auto iter = m_uplinkJobs_inter.begin(); iter != m_uplinkJobs_inter.end(); ++iter)
1116 {
1117 Ptr<UlJob> job = *iter;
1118
1119 ServiceFlow* serviceFlowJob = job->GetServiceFlow();
1120
1121 if (serviceFlowJob == serviceFlow)
1122 {
1123 size += job->GetSize();
1124 }
1125 }
1126 return size;
1127}
1128
1129void
1131{
1132 // Enqueue requests for uplink scheduler.
1133 Ptr<UlJob> job = CreateObject<UlJob>();
1134 Ptr<WimaxConnection> connection =
1135 GetBs()->GetConnectionManager()->GetConnection(bwRequestHdr.GetCid());
1136 SSRecord* ssRecord = GetBs()->GetSSManager()->GetSSRecord(connection->GetCid());
1137 ServiceFlow* serviceFlow = connection->GetServiceFlow();
1138
1139 uint32_t size = bwRequestHdr.GetBr();
1140 uint32_t pendingSize = GetPendingSize(serviceFlow);
1141
1142 if (size > pendingSize)
1143 {
1144 size -= pendingSize;
1145 }
1146 else
1147 {
1148 size = 0;
1149 }
1150
1151 if (size == 0)
1152 {
1153 return;
1154 }
1155
1156 Time deadline = DetermineDeadline(serviceFlow);
1157 Time currentTime = Simulator::Now();
1158 const Time& period = deadline; // So that deadline is properly updated..
1159
1160 NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
1161 << " at BS uplink scheduler, processing bandwidth request from."
1162 << ssRecord->GetMacAddress() << " and sf "
1163 << serviceFlow->GetSchedulingType() << " with deadline in "
1164 << deadline.As(Time::S) << " and size " << size << " aggreg size "
1165 << bwRequestHdr.GetBr());
1166
1167 // Record data in job
1168 job->SetSsRecord(ssRecord);
1169 job->SetServiceFlow(serviceFlow);
1170 job->SetSize(size);
1171 job->SetDeadline(deadline);
1172 job->SetReleaseTime(currentTime);
1173 job->SetSchedulingType(serviceFlow->GetSchedulingType());
1174 job->SetPeriod(period);
1175 job->SetType(DATA);
1176
1177 // Enqueue job in Uplink Scheduler
1178 switch (serviceFlow->GetSchedulingType())
1179 {
1182 break;
1185 break;
1187 EnqueueJob(UlJob::LOW, job);
1188 break;
1189 default:
1190 EnqueueJob(UlJob::LOW, job);
1191 break;
1192 }
1193}
1194
1195/*
1196 * Calculate Deadline of requests according to QoS parameter
1197 * */
1198Time
1200{
1201 uint32_t latency = serviceFlow->GetMaximumLatency();
1202 Time lastGrantTime = serviceFlow->GetRecord()->GetLastGrantTime();
1203 Time deadline = MilliSeconds(latency) + lastGrantTime;
1204 return deadline;
1205}
1206
1207void
1209{
1210 // virtual function on UplinkScheduler
1211 // this is not necessary on this implementation
1212}
1213
1214} // 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:77
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:260
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:273
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:254
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:286
bool GetHasServiceFlowBe() const
Check if at least one flow has scheduling type SF_TYPE_BE.
Definition: ss-record.cc:299
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:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
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:415
@ S
second
Definition: nstime.h:116
AttributeValue implementation for Time.
Definition: nstime.h:1413
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
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:1434
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
#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:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
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