A Discrete-Event Network Simulator
API
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"
22 #include "burst-profile-manager.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 
33 namespace ns3
34 {
35 
36 NS_LOG_COMPONENT_DEFINE("UplinkSchedulerMBQoS");
37 
38 NS_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 
55 TypeId
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)),
68  MakeTimeChecker());
69  return tid;
70 }
71 
72 void
74 {
76 }
77 
78 std::list<OfdmUlMapIe>
80 {
81  return m_uplinkAllocations;
82 }
83 
84 void
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 
143 uint32_t
145 {
146  return GetBs()->GetNrDlSymbols() * GetBs()->GetPhy()->GetPsPerSymbol() + GetBs()->GetTtg();
147 }
148 
149 void
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 
162 void
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) ||
192  (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS))
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 
223 void
225 {
226  m_uplinkAllocations.clear();
227  SetIsIrIntrvlAllocated(false);
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() +
329  MilliSeconds(
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
340  ServiceUnsolicitedGrants(ssRecord,
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  enum 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  {
419  ServiceUnsolicitedGrants(ssRecord,
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();
430  ServiceBandwidthRequestsBytes(serviceFlow,
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  enum 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  {
464  ServiceBandwidthRequests(ssRecord,
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  enum 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  {
498  ServiceBandwidthRequests(ssRecord,
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 
523 bool
525  enum 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 
574 uint32_t
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 
590  enum ServiceFlow::SchedulingType schedType,
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 
601 uint32_t
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 
643 void
645 {
646  switch (priority)
647  {
648  case UlJob::HIGH:
649  m_uplinkJobs_high.push_back(job);
650  break;
651  case UlJob::INTERMEDIATE:
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;
669  case UlJob::INTERMEDIATE:
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 
680 void
681 UplinkSchedulerMBQoS::CheckDeadline(uint32_t& availableSymbols)
682 {
683  // for each request in the imermediate 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 
772 void
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);
865  EnqueueJob(UlJob::HIGH, job);
866  }
867  }
868 }
869 
870 void
872  enum 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 
938 void
940  enum 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 
964 bool
966  enum 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 
1028 void
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  {
1044  SetIsIrIntrvlAllocated(true);
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 
1069 void
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  {
1081  case ServiceFlow::SF_TYPE_UGS: {
1082  if (serviceFlow->GetIsMulticast() == true)
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;
1114  case ServiceFlow::SF_TYPE_BE: {
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 
1123 uint32_t
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 
1146 void
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  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  * */
1215 Time
1217 {
1218  uint32_t latency = serviceFlow->GetMaximumLatency();
1219  Time lastGrantTime = serviceFlow->GetRecord()->GetLastGrantTime();
1220  Time deadline = MilliSeconds(latency) + lastGrantTime;
1221  return deadline;
1222 }
1223 
1224 void
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(enum 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
enum ServiceFlow::SchedulingType GetSchedulingType() const
Get scheduling type.
uint32_t GetSfid() const
Get SFID.
uint32_t GetMaximumLatency() const
Get maximum latency.
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.
void SetUnsolicitedGrantInterval(uint16_t unsolicitedGrantInterval)
Set unsolicited grant interval.
ServiceFlowRecord * GetRecord() const
Get service flow record.
enum WimaxPhy::ModulationType GetModulation() const
Get modulation.
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:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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 AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1424
const char * NS_LOG
Control which logging components are enabled.
#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_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
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
@ LOG_DEBUG
Rare ad-hoc debug messages.
Definition: log.h:103
#define list
SortProcessPtr structure.
Definition: ul-job.h:241