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 (std::vector<SSRecord*>::iterator iter = ssRecords->begin(); iter != ssRecords->end();
186  ++iter)
187  {
188  SSRecord* ssRecord = *iter;
189 
190  if (ssRecord->GetIsBroadcastSS())
191  {
192  continue;
193  }
194  Cid cid = ssRecord->GetBasicCid();
195  OfdmUlMapIe ulMapIe;
196  ulMapIe.SetCid(cid);
197 
198  if (ssRecord->GetPollForRanging() &&
200  {
201  // SS's ranging is not yet complete
202  // allocating invited initial ranging interval
204  allocationSize = GetBs()->GetRangReqOppSize();
206 
207  if (availableSymbols >= allocationSize)
208  {
209  AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
210  }
211  else
212  {
213  break;
214  }
215  }
216  else
217  {
218  WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
219 
220  // need to update because modulation/FEC to UIUC mapping may vary over time
221  ulMapIe.SetUiuc(GetBs()->GetBurstProfileManager()->GetBurstProfile(
222  modulationType,
224 
225  // establish service flows for SS
227  !ssRecord->GetAreServiceFlowsAllocated())
228  {
229  // allocating grant (with arbitrary size) to allow SS to send DSA messages DSA-REQ
230  // and DSA-ACK only one DSA allocation per frame
231  if (!allocationForDsa)
232  {
233  allocationSize =
234  GetBs()->GetPhy()->GetNrSymbols(sizeof(DsaReq), modulationType);
235 
236  if (availableSymbols >= allocationSize)
237  {
238  AddUplinkAllocation(ulMapIe,
239  allocationSize,
240  symbolsToAllocation,
241  availableSymbols);
242  allocationForDsa = true;
243  }
244  else
245  {
246  break;
247  }
248  }
249  }
250  else
251  {
252  // all service flows associated to SS are established now
253 
254  /*allocating grants for data transmission for UGS flows (Data Grant Burst Type
255  IEs, 6.3.7.4.3.3) (grant has been referred by different names e.g. transmission
256  opportunity, slot, uplink allocation, etc)*/
257  ServiceUnsolicitedGrants(ssRecord,
259  ulMapIe,
260  modulationType,
261  symbolsToAllocation,
262  availableSymbols);
263 
264  // allocate unicast polls for rtPS flows if bandwidth is available
265  if (availableSymbols)
266  {
267  ServiceUnsolicitedGrants(ssRecord,
269  ulMapIe,
270  modulationType,
271  symbolsToAllocation,
272  availableSymbols);
273  }
274  // allocate unicast polls for nrtPS flows if bandwidth is available
275  if (availableSymbols)
276  {
277  ServiceUnsolicitedGrants(ssRecord,
279  ulMapIe,
280  modulationType,
281  symbolsToAllocation,
282  availableSymbols);
283  }
284  // finally allocate unicast polls for BE flows if bandwidth is available
285  if (availableSymbols)
286  {
287  ServiceUnsolicitedGrants(ssRecord,
289  ulMapIe,
290  modulationType,
291  symbolsToAllocation,
292  availableSymbols);
293  }
294 
295  // now allocating grants for non-UGS flows (i.e., in response of bandwidth requests)
296 
297  if (availableSymbols)
298  {
299  ServiceBandwidthRequests(ssRecord,
301  ulMapIe,
302  modulationType,
303  symbolsToAllocation,
304  availableSymbols);
305  }
306  // allocate unicast polls for nrtPS flows if bandwidth is available
307  if (availableSymbols)
308  {
309  ServiceBandwidthRequests(ssRecord,
311  ulMapIe,
312  modulationType,
313  symbolsToAllocation,
314  availableSymbols);
315  }
316  // finally allocate unicast polls for BE flows if bandwidth is available
317  if (availableSymbols)
318  {
319  ServiceBandwidthRequests(ssRecord,
321  ulMapIe,
322  modulationType,
323  symbolsToAllocation,
324  availableSymbols);
325  }
326  }
327  }
328  }
329  OfdmUlMapIe ulMapIeEnd;
330 
331  ulMapIeEnd.SetCid(Cid::InitialRanging());
332  ulMapIeEnd.SetStartTime(symbolsToAllocation);
334  ulMapIeEnd.SetDuration(0);
335  m_uplinkAllocations.push_back(ulMapIeEnd);
336 
337  // setting DL/UL subframe allocation for the next frame
338  GetBs()->GetBandwidthManager()->SetSubframeRatio();
339 }
340 
341 void
343  enum ServiceFlow::SchedulingType schedulingType,
344  OfdmUlMapIe& ulMapIe,
345  const WimaxPhy::ModulationType modulationType,
346  uint32_t& symbolsToAllocation,
347  uint32_t& availableSymbols)
348 {
349  uint32_t allocationSize = 0; // size in symbols
350  uint8_t uiuc = ulMapIe.GetUiuc(); // SS's burst profile
351  std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
352 
353  for (std::vector<ServiceFlow*>::iterator iter = serviceFlows.begin();
354  iter != serviceFlows.end();
355  ++iter)
356  {
357  ServiceFlow* serviceFlow = *iter;
358 
359  /* in case of rtPS, nrtPS and BE, allocating unicast polls for bandwidth requests (Request
360  IEs, 6.3.7.4.3.1). in case of UGS, allocating grants for data transmission (Data Grant
361  Burst Type IEs, 6.3.7.4.3.3) (grant has been referred in this code by different names e.g.
362  transmission opportunity, slot, allocation, etc) */
363 
364  allocationSize =
365  GetBs()->GetBandwidthManager()->CalculateAllocationSize(ssRecord, serviceFlow);
366  // verifying that minimum reserved traffic rate of nrtPS flow is maintained
367  if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS)
368  {
369  Time currentTime = Simulator::Now();
370  ServiceFlowRecord* record = serviceFlow->GetRecord();
371  if (currentTime - record->GetGrantTimeStamp() > Seconds(1))
372  {
373  uint32_t bps = (record->GetBwSinceLastExpiry() * 8);
374  if (bps < serviceFlow->GetMinReservedTrafficRate())
375  {
376  ServiceBandwidthRequests(serviceFlow,
377  schedulingType,
378  ulMapIe,
379  modulationType,
380  symbolsToAllocation,
381  availableSymbols);
382  record->SetBwSinceLastExpiry(0);
383  record->SetGrantTimeStamp(currentTime);
384  }
385  }
386  }
387 
388  if (availableSymbols < allocationSize)
389  {
390  break;
391  }
392 
393  if (allocationSize > 0)
394  {
395  ulMapIe.SetStartTime(symbolsToAllocation);
396  if (serviceFlow->GetSchedulingType() != ServiceFlow::SF_TYPE_UGS)
397  {
398  // special burst profile with most robust modulation type is used for unicast polls
399  // (Request IEs)
401  }
402  }
403  else
404  {
405  continue;
406  }
407 
408  NS_LOG_DEBUG(", CID: " << serviceFlow->GetConnection()->GetCid()
409  << ", SFID: " << serviceFlow->GetSfid());
410 
411  AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
412  ulMapIe.SetUiuc(uiuc);
413  }
414 }
415 
416 void
418  enum ServiceFlow::SchedulingType schedulingType,
419  OfdmUlMapIe& ulMapIe,
420  const WimaxPhy::ModulationType modulationType,
421  uint32_t& symbolsToAllocation,
422  uint32_t& availableSymbols)
423 {
424  std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
425 
426  for (std::vector<ServiceFlow*>::iterator iter = serviceFlows.begin();
427  iter != serviceFlows.end();
428  ++iter)
429  {
430  if (!ServiceBandwidthRequests(*iter,
431  schedulingType,
432  ulMapIe,
433  modulationType,
434  symbolsToAllocation,
435  availableSymbols))
436  {
437  break;
438  }
439  }
440 }
441 
442 bool
444  enum ServiceFlow::SchedulingType schedulingType,
445  OfdmUlMapIe& ulMapIe,
446  const WimaxPhy::ModulationType modulationType,
447  uint32_t& symbolsToAllocation,
448  uint32_t& availableSymbols)
449 {
450  uint32_t allocSizeBytes = 0;
451  uint32_t allocSizeSymbols = 0;
452  uint16_t sduSize = 0;
453 
454  ServiceFlowRecord* record = serviceFlow->GetRecord();
455  sduSize = serviceFlow->GetSduSize();
456 
457  uint32_t requiredBandwidth = record->GetRequestedBandwidth() - record->GetGrantedBandwidth();
458  if (requiredBandwidth > 0)
459  {
460  if (sduSize > 0)
461  {
462  // if SDU size is mentioned, allocate grant of that size
463  allocSizeBytes = sduSize;
464  allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(sduSize, modulationType);
465  }
466  else
467  {
468  allocSizeBytes = requiredBandwidth;
469  allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(requiredBandwidth, modulationType);
470  }
471 
472  if (availableSymbols >= allocSizeSymbols)
473  {
474  record->UpdateGrantedBandwidth(allocSizeBytes);
475 
476  if (schedulingType == ServiceFlow::SF_TYPE_NRTPS)
477  {
478  record->SetBwSinceLastExpiry(allocSizeBytes);
479  }
480 
481  AddUplinkAllocation(ulMapIe, allocSizeSymbols, symbolsToAllocation, availableSymbols);
482  }
483  else
484  {
485  return false;
486  }
487  }
488  return true;
489 }
490 
491 void
493  uint32_t& availableSymbols)
494 {
495  Time ssUlStartTime =
496  Seconds(CalculateAllocationStartTime() * GetBs()->GetPsDuration().GetSeconds());
497  SetNrIrOppsAllocated(GetBs()->GetLinkManager()->CalculateRangingOppsToAllocate());
498  uint32_t allocationSize = GetNrIrOppsAllocated() * GetBs()->GetRangReqOppSize();
499  Time timeSinceLastIrInterval = Simulator::Now() - GetTimeStampIrInterval();
500 
501  // adding one frame because may be the time has not elapsed now but will elapse before the next
502  // frame is sent
503  if (timeSinceLastIrInterval + GetBs()->GetPhy()->GetFrameDuration() >
504  GetBs()->GetInitialRangingInterval() &&
505  availableSymbols >= allocationSize)
506  {
508  OfdmUlMapIe ulMapIeIr;
509  ulMapIeIr.SetCid((GetBs()->GetBroadcastConnection())->GetCid());
510  ulMapIeIr.SetStartTime(symbolsToAllocation);
512 
513  NS_LOG_DEBUG("BS uplink scheduler, initial ranging allocation, size: "
514  << allocationSize << " symbols"
515  << ", modulation: BPSK 1/2");
516 
517  // marking start and end of each TO, only for debugging
518  for (uint8_t i = 0; i < GetNrIrOppsAllocated(); i++)
519  {
520  GetBs()->MarkRangingOppStart(
521  ssUlStartTime +
522  Seconds(symbolsToAllocation * GetBs()->GetSymbolDuration().GetSeconds()) +
523  Seconds(i * GetBs()->GetRangReqOppSize() *
524  GetBs()->GetSymbolDuration().GetSeconds()));
525  }
526 
527  AddUplinkAllocation(ulMapIeIr, allocationSize, symbolsToAllocation, availableSymbols);
529  }
530 }
531 
532 void
534 {
535  uint8_t delayNrFrames = 1;
536  uint32_t bitsPerSecond = serviceFlow->GetMinReservedTrafficRate();
537  WimaxPhy::ModulationType modulation;
538  uint32_t bytesPerFrame =
539  (uint32_t((double)(bitsPerSecond)*GetBs()->GetPhy()->GetFrameDuration().GetSeconds())) / 8;
540  uint32_t frameDurationMSec = GetBs()->GetPhy()->GetFrameDuration().GetMilliSeconds();
541 
542  switch (serviceFlow->GetSchedulingType())
543  {
545  if (serviceFlow->GetIsMulticast() == true)
546  {
547  modulation = serviceFlow->GetModulation();
548  }
549  else
550  {
551  modulation = ssRecord->GetModulationType();
552  }
553  uint32_t grantSize = GetBs()->GetPhy()->GetNrSymbols(bytesPerFrame, modulation);
554  serviceFlow->GetRecord()->SetGrantSize(grantSize);
555 
556  uint32_t toleratedJitter = serviceFlow->GetToleratedJitter();
557 
558  if (toleratedJitter > frameDurationMSec)
559  {
560  delayNrFrames = (uint8_t)(toleratedJitter / frameDurationMSec);
561  }
562 
563  uint16_t interval = delayNrFrames * frameDurationMSec;
564  serviceFlow->SetUnsolicitedGrantInterval(interval);
565  }
566  break;
568  if (serviceFlow->GetSduSize() > bytesPerFrame)
569  {
570  delayNrFrames = (uint8_t)(serviceFlow->GetSduSize() / bytesPerFrame);
571  }
572 
573  uint16_t interval = delayNrFrames * frameDurationMSec;
574  serviceFlow->SetUnsolicitedPollingInterval(interval);
575  }
576  break;
578  // no real-time guarantees are given to NRTPS, serviced based on available bandwidth
579  }
580  break;
582  // no real-time guarantees are given to BE, serviced based on available bandwidth
583  }
584  break;
585  default:
586  NS_FATAL_ERROR("Invalid scheduling type");
587  }
588 }
589 
590 void
592 {
593  // virtual function on UplinkScheduler
594  // this is not necessary on this implementation
595 }
596 
597 void
599 {
600  // m_grantedBandwidth must be reset to zero
601  uint32_t grantedBandwidth = 0;
602  sfr->SetGrantedBandwidth(grantedBandwidth);
603 }
604 
605 } // 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:78
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(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
bool GetIsBroadcastSS() const
Get is broadcast SS.
Definition: ss-record.cc:256
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
enum ServiceFlow::SchedulingType GetSchedulingType() const
Get scheduling type.
uint32_t GetSfid() const
Get SFID.
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.
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 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:199
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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:1336
Every class exported by the ns3 library is enclosed in the ns3 namespace.