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