A Discrete-Event Network Simulator
API
bs-uplink-scheduler-simple.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007,2008 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
18  */
19 
21 
22 #include "bandwidth-manager.h"
23 #include "bs-link-manager.h"
24 #include "bs-net-device.h"
25 #include "burst-profile-manager.h"
26 #include "cid.h"
27 #include "service-flow-record.h"
28 #include "service-flow.h"
29 #include "ss-manager.h"
30 #include "ss-record.h"
31 
32 #include "ns3/log.h"
33 #include "ns3/simulator.h"
34 #include "ns3/uinteger.h"
35 
36 namespace ns3
37 {
38 
39 NS_LOG_COMPONENT_DEFINE("UplinkSchedulerSimple");
40 
41 NS_OBJECT_ENSURE_REGISTERED(UplinkSchedulerSimple);
42 
44 {
45  SetBs(nullptr);
52 }
53 
55 {
56  SetBs(bs);
63 }
64 
66 {
67  SetBs(nullptr);
68  m_uplinkAllocations.clear();
69 }
70 
71 void
73 {
74 }
75 
76 TypeId
78 {
79  static TypeId tid = TypeId("ns3::UplinkSchedulerSimple")
81  .SetGroupName("Wimax")
82  .AddConstructor<UplinkSchedulerSimple>();
83  return tid;
84 }
85 
86 std::list<OfdmUlMapIe>
88 {
89  return m_uplinkAllocations;
90 }
91 
92 void
94  bool& updateUcd,
95  bool& sendDcd,
96  bool& sendUcd)
97 {
98  /*DCD and UCD shall actually be updated when channel or burst profile definitions
99  change. burst profiles are updated based on number of SSs, network conditions and etc.
100  for now temporarily assuming DCD/UCD shall be updated every time */
101 
102  uint32_t randNr = rand();
103  if (randNr % 5 == 0 || GetBs()->GetNrDcdSent() == 0)
104  {
105  sendDcd = true;
106  }
107 
108  randNr = rand();
109  if (randNr % 5 == 0 || GetBs()->GetNrUcdSent() == 0)
110  {
111  sendUcd = true;
112  }
113 
114  // -------------------------------------
115  // additional, just to send more frequently
116  if (!sendDcd)
117  {
118  randNr = rand();
119  if (randNr % 4 == 0)
120  {
121  sendDcd = true;
122  }
123  }
124 
125  if (!sendUcd)
126  {
127  randNr = rand();
128  if (randNr % 4 == 0)
129  {
130  sendUcd = true;
131  }
132  }
133  // -------------------------------------
134 
135  Time timeSinceLastDcd = Simulator::Now() - GetDcdTimeStamp();
136  Time timeSinceLastUcd = Simulator::Now() - GetUcdTimeStamp();
137 
138  if (timeSinceLastDcd > GetBs()->GetDcdInterval())
139  {
140  sendDcd = true;
142  }
143 
144  if (timeSinceLastUcd > GetBs()->GetUcdInterval())
145  {
146  sendUcd = true;
148  }
149 }
150 
151 uint32_t
153 {
154  return GetBs()->GetNrDlSymbols() * GetBs()->GetPhy()->GetPsPerSymbol() + GetBs()->GetTtg();
155 }
156 
157 void
159  const uint32_t& allocationSize,
160  uint32_t& symbolsToAllocation,
161  uint32_t& availableSymbols)
162 {
163  ulMapIe.SetDuration(allocationSize);
164  ulMapIe.SetStartTime(symbolsToAllocation);
165  m_uplinkAllocations.push_back(ulMapIe);
166  symbolsToAllocation += allocationSize;
167  availableSymbols -= allocationSize;
168 }
169 
170 void
172 {
173  m_uplinkAllocations.clear();
174  SetIsIrIntrvlAllocated(false);
176  bool allocationForDsa = false;
177 
178  uint32_t symbolsToAllocation = 0;
179  uint32_t allocationSize = 0; // size in symbols
180  uint32_t availableSymbols = GetBs()->GetNrUlSymbols();
181 
182  AllocateInitialRangingInterval(symbolsToAllocation, availableSymbols);
183 
184  std::vector<SSRecord*>* ssRecords = GetBs()->GetSSManager()->GetSSRecords();
185  for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
186  {
187  SSRecord* ssRecord = *iter;
188 
189  if (ssRecord->GetIsBroadcastSS())
190  {
191  continue;
192  }
193  Cid cid = ssRecord->GetBasicCid();
194  OfdmUlMapIe ulMapIe;
195  ulMapIe.SetCid(cid);
196 
197  if (ssRecord->GetPollForRanging() &&
199  {
200  // SS's ranging is not yet complete
201  // allocating invited initial ranging interval
203  allocationSize = GetBs()->GetRangReqOppSize();
205 
206  if (availableSymbols >= allocationSize)
207  {
208  AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
209  }
210  else
211  {
212  break;
213  }
214  }
215  else
216  {
217  WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
218 
219  // need to update because modulation/FEC to UIUC mapping may vary over time
220  ulMapIe.SetUiuc(GetBs()->GetBurstProfileManager()->GetBurstProfile(
221  modulationType,
223 
224  // establish service flows for SS
226  !ssRecord->GetAreServiceFlowsAllocated())
227  {
228  // allocating grant (with arbitrary size) to allow SS to send DSA messages DSA-REQ
229  // and DSA-ACK only one DSA allocation per frame
230  if (!allocationForDsa)
231  {
232  allocationSize =
233  GetBs()->GetPhy()->GetNrSymbols(sizeof(DsaReq), modulationType);
234 
235  if (availableSymbols >= allocationSize)
236  {
237  AddUplinkAllocation(ulMapIe,
238  allocationSize,
239  symbolsToAllocation,
240  availableSymbols);
241  allocationForDsa = true;
242  }
243  else
244  {
245  break;
246  }
247  }
248  }
249  else
250  {
251  // all service flows associated to SS are established now
252 
253  /*allocating grants for data transmission for UGS flows (Data Grant Burst Type
254  IEs, 6.3.7.4.3.3) (grant has been referred by different names e.g. transmission
255  opportunity, slot, uplink allocation, etc)*/
256  ServiceUnsolicitedGrants(ssRecord,
258  ulMapIe,
259  modulationType,
260  symbolsToAllocation,
261  availableSymbols);
262 
263  // allocate unicast polls for rtPS flows if bandwidth is available
264  if (availableSymbols)
265  {
266  ServiceUnsolicitedGrants(ssRecord,
268  ulMapIe,
269  modulationType,
270  symbolsToAllocation,
271  availableSymbols);
272  }
273  // allocate unicast polls for nrtPS flows if bandwidth is available
274  if (availableSymbols)
275  {
276  ServiceUnsolicitedGrants(ssRecord,
278  ulMapIe,
279  modulationType,
280  symbolsToAllocation,
281  availableSymbols);
282  }
283  // finally allocate unicast polls for BE flows if bandwidth is available
284  if (availableSymbols)
285  {
286  ServiceUnsolicitedGrants(ssRecord,
288  ulMapIe,
289  modulationType,
290  symbolsToAllocation,
291  availableSymbols);
292  }
293 
294  // now allocating grants for non-UGS flows (i.e., in response of bandwidth requests)
295 
296  if (availableSymbols)
297  {
298  ServiceBandwidthRequests(ssRecord,
300  ulMapIe,
301  modulationType,
302  symbolsToAllocation,
303  availableSymbols);
304  }
305  // allocate unicast polls for nrtPS flows if bandwidth is available
306  if (availableSymbols)
307  {
308  ServiceBandwidthRequests(ssRecord,
310  ulMapIe,
311  modulationType,
312  symbolsToAllocation,
313  availableSymbols);
314  }
315  // finally allocate unicast polls for BE flows if bandwidth is available
316  if (availableSymbols)
317  {
318  ServiceBandwidthRequests(ssRecord,
320  ulMapIe,
321  modulationType,
322  symbolsToAllocation,
323  availableSymbols);
324  }
325  }
326  }
327  }
328  OfdmUlMapIe ulMapIeEnd;
329 
330  ulMapIeEnd.SetCid(Cid::InitialRanging());
331  ulMapIeEnd.SetStartTime(symbolsToAllocation);
333  ulMapIeEnd.SetDuration(0);
334  m_uplinkAllocations.push_back(ulMapIeEnd);
335 
336  // setting DL/UL subframe allocation for the next frame
337  GetBs()->GetBandwidthManager()->SetSubframeRatio();
338 }
339 
340 void
342  ServiceFlow::SchedulingType schedulingType,
343  OfdmUlMapIe& ulMapIe,
344  const WimaxPhy::ModulationType modulationType,
345  uint32_t& symbolsToAllocation,
346  uint32_t& availableSymbols)
347 {
348  uint32_t allocationSize = 0; // size in symbols
349  uint8_t uiuc = ulMapIe.GetUiuc(); // SS's burst profile
350  std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
351 
352  for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
353  {
354  ServiceFlow* serviceFlow = *iter;
355 
356  /* in case of rtPS, nrtPS and BE, allocating unicast polls for bandwidth requests (Request
357  IEs, 6.3.7.4.3.1). in case of UGS, allocating grants for data transmission (Data Grant
358  Burst Type IEs, 6.3.7.4.3.3) (grant has been referred in this code by different names e.g.
359  transmission opportunity, slot, allocation, etc) */
360 
361  allocationSize =
362  GetBs()->GetBandwidthManager()->CalculateAllocationSize(ssRecord, serviceFlow);
363  // verifying that minimum reserved traffic rate of nrtPS flow is maintained
364  if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS)
365  {
366  Time currentTime = Simulator::Now();
367  ServiceFlowRecord* record = serviceFlow->GetRecord();
368  if (currentTime - record->GetGrantTimeStamp() > Seconds(1))
369  {
370  uint32_t bps = (record->GetBwSinceLastExpiry() * 8);
371  if (bps < serviceFlow->GetMinReservedTrafficRate())
372  {
373  ServiceBandwidthRequests(serviceFlow,
374  schedulingType,
375  ulMapIe,
376  modulationType,
377  symbolsToAllocation,
378  availableSymbols);
379  record->SetBwSinceLastExpiry(0);
380  record->SetGrantTimeStamp(currentTime);
381  }
382  }
383  }
384 
385  if (availableSymbols < allocationSize)
386  {
387  break;
388  }
389 
390  if (allocationSize > 0)
391  {
392  ulMapIe.SetStartTime(symbolsToAllocation);
393  if (serviceFlow->GetSchedulingType() != ServiceFlow::SF_TYPE_UGS)
394  {
395  // special burst profile with most robust modulation type is used for unicast polls
396  // (Request IEs)
398  }
399  }
400  else
401  {
402  continue;
403  }
404 
405  NS_LOG_DEBUG(", CID: " << serviceFlow->GetConnection()->GetCid()
406  << ", SFID: " << serviceFlow->GetSfid());
407 
408  AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
409  ulMapIe.SetUiuc(uiuc);
410  }
411 }
412 
413 void
415  ServiceFlow::SchedulingType schedulingType,
416  OfdmUlMapIe& ulMapIe,
417  const WimaxPhy::ModulationType modulationType,
418  uint32_t& symbolsToAllocation,
419  uint32_t& availableSymbols)
420 {
421  std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
422 
423  for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
424  {
425  if (!ServiceBandwidthRequests(*iter,
426  schedulingType,
427  ulMapIe,
428  modulationType,
429  symbolsToAllocation,
430  availableSymbols))
431  {
432  break;
433  }
434  }
435 }
436 
437 bool
439  ServiceFlow::SchedulingType schedulingType,
440  OfdmUlMapIe& ulMapIe,
441  const WimaxPhy::ModulationType modulationType,
442  uint32_t& symbolsToAllocation,
443  uint32_t& availableSymbols)
444 {
445  uint32_t allocSizeBytes = 0;
446  uint32_t allocSizeSymbols = 0;
447  uint16_t sduSize = 0;
448 
449  ServiceFlowRecord* record = serviceFlow->GetRecord();
450  sduSize = serviceFlow->GetSduSize();
451 
452  uint32_t requiredBandwidth = record->GetRequestedBandwidth() - record->GetGrantedBandwidth();
453  if (requiredBandwidth > 0)
454  {
455  if (sduSize > 0)
456  {
457  // if SDU size is mentioned, allocate grant of that size
458  allocSizeBytes = sduSize;
459  allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(sduSize, modulationType);
460  }
461  else
462  {
463  allocSizeBytes = requiredBandwidth;
464  allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(requiredBandwidth, modulationType);
465  }
466 
467  if (availableSymbols >= allocSizeSymbols)
468  {
469  record->UpdateGrantedBandwidth(allocSizeBytes);
470 
471  if (schedulingType == ServiceFlow::SF_TYPE_NRTPS)
472  {
473  record->SetBwSinceLastExpiry(allocSizeBytes);
474  }
475 
476  AddUplinkAllocation(ulMapIe, allocSizeSymbols, symbolsToAllocation, availableSymbols);
477  }
478  else
479  {
480  return false;
481  }
482  }
483  return true;
484 }
485 
486 void
488  uint32_t& availableSymbols)
489 {
490  Time ssUlStartTime =
491  Seconds(CalculateAllocationStartTime() * GetBs()->GetPsDuration().GetSeconds());
492  SetNrIrOppsAllocated(GetBs()->GetLinkManager()->CalculateRangingOppsToAllocate());
493  uint32_t allocationSize = GetNrIrOppsAllocated() * GetBs()->GetRangReqOppSize();
494  Time timeSinceLastIrInterval = Simulator::Now() - GetTimeStampIrInterval();
495 
496  // adding one frame because may be the time has not elapsed now but will elapse before the next
497  // frame is sent
498  if (timeSinceLastIrInterval + GetBs()->GetPhy()->GetFrameDuration() >
499  GetBs()->GetInitialRangingInterval() &&
500  availableSymbols >= allocationSize)
501  {
503  OfdmUlMapIe ulMapIeIr;
504  ulMapIeIr.SetCid((GetBs()->GetBroadcastConnection())->GetCid());
505  ulMapIeIr.SetStartTime(symbolsToAllocation);
507 
508  NS_LOG_DEBUG("BS uplink scheduler, initial ranging allocation, size: "
509  << allocationSize << " symbols"
510  << ", modulation: BPSK 1/2");
511 
512  // marking start and end of each TO, only for debugging
513  for (uint8_t i = 0; i < GetNrIrOppsAllocated(); i++)
514  {
515  GetBs()->MarkRangingOppStart(
516  ssUlStartTime +
517  Seconds(symbolsToAllocation * GetBs()->GetSymbolDuration().GetSeconds()) +
518  Seconds(i * GetBs()->GetRangReqOppSize() *
519  GetBs()->GetSymbolDuration().GetSeconds()));
520  }
521 
522  AddUplinkAllocation(ulMapIeIr, allocationSize, symbolsToAllocation, availableSymbols);
524  }
525 }
526 
527 void
529 {
530  uint8_t delayNrFrames = 1;
531  uint32_t bitsPerSecond = serviceFlow->GetMinReservedTrafficRate();
532  WimaxPhy::ModulationType modulation;
533  uint32_t bytesPerFrame =
534  (uint32_t((double)(bitsPerSecond)*GetBs()->GetPhy()->GetFrameDuration().GetSeconds())) / 8;
535  uint32_t frameDurationMSec = GetBs()->GetPhy()->GetFrameDuration().GetMilliSeconds();
536 
537  switch (serviceFlow->GetSchedulingType())
538  {
540  if (serviceFlow->GetIsMulticast())
541  {
542  modulation = serviceFlow->GetModulation();
543  }
544  else
545  {
546  modulation = ssRecord->GetModulationType();
547  }
548  uint32_t grantSize = GetBs()->GetPhy()->GetNrSymbols(bytesPerFrame, modulation);
549  serviceFlow->GetRecord()->SetGrantSize(grantSize);
550 
551  uint32_t toleratedJitter = serviceFlow->GetToleratedJitter();
552 
553  if (toleratedJitter > frameDurationMSec)
554  {
555  delayNrFrames = (uint8_t)(toleratedJitter / frameDurationMSec);
556  }
557 
558  uint16_t interval = delayNrFrames * frameDurationMSec;
559  serviceFlow->SetUnsolicitedGrantInterval(interval);
560  }
561  break;
563  if (serviceFlow->GetSduSize() > bytesPerFrame)
564  {
565  delayNrFrames = (uint8_t)(serviceFlow->GetSduSize() / bytesPerFrame);
566  }
567 
568  uint16_t interval = delayNrFrames * frameDurationMSec;
569  serviceFlow->SetUnsolicitedPollingInterval(interval);
570  }
571  break;
573  // no real-time guarantees are given to NRTPS, serviced based on available bandwidth
574  }
575  break;
577  // no real-time guarantees are given to BE, serviced based on available bandwidth
578  }
579  break;
580  default:
581  NS_FATAL_ERROR("Invalid scheduling type");
582  }
583 }
584 
585 void
587 {
588  // virtual function on UplinkScheduler
589  // this is not necessary on this implementation
590 }
591 
592 void
594 {
595  // m_grantedBandwidth must be reset to zero
596  uint32_t grantedBandwidth = 0;
597  sfr->SetGrantedBandwidth(grantedBandwidth);
598 }
599 
600 } // namespace ns3
This class implements the bandwidth-request mac Header as described by IEEE Standard for Local and me...
Cid class.
Definition: cid.h:37
static Cid InitialRanging()
Definition: cid.cc:87
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
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
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
bool GetIsBroadcastSS() const
Get is broadcast SS.
Definition: ss-record.cc:254
WimaxPhy::ModulationType GetModulationType() const
Get modulation type.
Definition: ss-record.cc:167
This class implements service flows as described by the IEEE-802.16 standard.
Definition: service-flow.h:43
uint32_t GetSfid() const
Get SFID.
ServiceFlow::SchedulingType GetSchedulingType() const
Get scheduling type.
SchedulingType
section 11.13.11 Service flow scheduling type, page 701
Definition: service-flow.h:62
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 GetRequestedBandwidth() const
void SetGrantSize(uint32_t grantSize)
Set the grant size (only for UGS service flows)
uint32_t GetGrantedBandwidth() const
void SetBwSinceLastExpiry(uint32_t bwSinceLastExpiry)
set BW since last expiry
void UpdateGrantedBandwidth(uint32_t grantedBandwidth)
update the granted bandwidth
uint32_t GetBwSinceLastExpiry() const
void SetGrantTimeStamp(Time grantTimeStamp)
Set the grant time stamp.
void SetGrantedBandwidth(uint32_t grantedBandwidth)
set the granted bandwidth
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
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
ModulationType
ModulationType enumeration.
Definition: wimax-phy.h:54
#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:1326
Every class exported by the ns3 library is enclosed in the ns3 namespace.