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