satellite-beam-scheduler.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Magister Solutions Ltd
4  * Copyright (c) 2018 CNES
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Sami Rantanen <sami.rantanen@magister.fi>
20  * Author: Mathias Ettinger <mettinger@toulouse.viveris.com>
21  */
22 
24 
25 #include "../stats/satellite-frame-symbol-load-probe.h"
26 #include "../stats/satellite-frame-user-load-probe.h"
29 #include "satellite-dama-entry.h"
31 #include "satellite-id-mapper.h"
36 
37 #include <ns3/address.h>
38 #include <ns3/boolean.h>
39 #include <ns3/double.h>
40 #include <ns3/enum.h>
41 #include <ns3/ipv4-address.h>
42 #include <ns3/log.h>
43 #include <ns3/mac48-address.h>
44 #include <ns3/singleton.h>
45 
46 #include <algorithm>
47 #include <sstream>
48 #include <utility>
49 
50 NS_LOG_COMPONENT_DEFINE("SatBeamScheduler");
51 
52 namespace ns3
53 {
54 
55 // UtInfo class declarations for SatBeamScheduler
56 SatBeamScheduler::SatUtInfo::SatUtInfo(Ptr<SatDamaEntry> damaEntry,
57  Ptr<SatCnoEstimator> cnoEstimator,
58  Time controlSlotOffset,
59  bool controlSlotsEnabled)
60  : m_damaEntry(damaEntry),
61  m_cnoEstimator(cnoEstimator),
62  m_controlSlotsEnabled(controlSlotsEnabled)
63 {
64  NS_LOG_FUNCTION(this);
65 
66  SetControlSlotGenerationTime(controlSlotOffset);
67 }
68 
69 Ptr<SatDamaEntry>
71 {
72  NS_LOG_FUNCTION(this);
73 
74  return m_damaEntry;
75 }
76 
77 void
79 {
80  NS_LOG_FUNCTION(this);
81 
82  // map to sum up RBDC requests per RC
83  std::map<uint8_t, uint16_t> rbdcReqs;
84 
85  for (CrMsgContainer_t::const_iterator crIt = m_crContainer.begin(); crIt != m_crContainer.end();
86  crIt++)
87  {
88  SatCrMessage::RequestContainer_t crContent = (*crIt)->GetCapacityRequestContent();
89 
90  for (SatCrMessage::RequestContainer_t::const_iterator descriptorIt = crContent.begin();
91  descriptorIt != crContent.end();
92  descriptorIt++)
93  {
94  switch (descriptorIt->first.second)
95  {
96  case SatEnums::DA_RBDC: {
97  rbdcReqs[descriptorIt->first.first] += descriptorIt->second;
98  break;
99  }
100 
101  case SatEnums::DA_VBDC: {
102  m_damaEntry->ResetVolumeBacklogPersistence();
103  m_damaEntry->UpdateVbdcInBytes(descriptorIt->first.first, descriptorIt->second);
104  break;
105  }
106 
107  case SatEnums::DA_AVBDC: {
108  m_damaEntry->ResetVolumeBacklogPersistence();
109  m_damaEntry->SetVbdcInBytes(descriptorIt->first.first, descriptorIt->second);
110  break;
111  }
112 
113  default:
114  break;
115  }
116  }
117  }
118 
119  // update RBDC with summed up requests
120  for (std::map<uint8_t, uint16_t>::iterator it = rbdcReqs.begin(); it != rbdcReqs.end(); it++)
121  {
122  m_damaEntry->ResetDynamicRatePersistence();
123  m_damaEntry->UpdateRbdcInKbps(it->first, it->second);
124  }
125 
126  // clear container when CRs processed
127  m_crContainer.clear();
128 }
129 
130 double
132 {
133  NS_LOG_FUNCTION(this);
134 
135  return m_cnoEstimator->GetCnoEstimation();
136 }
137 
138 void
140 {
141  NS_LOG_FUNCTION(this << sample);
142 
143  m_cnoEstimator->AddSample(sample);
144 }
145 
146 void
148 {
149  NS_LOG_FUNCTION(this << crMsg);
150 
151  m_crContainer.push_back(crMsg);
152 }
153 
154 void
156 {
157  NS_LOG_FUNCTION(this);
158 
159  m_crContainer.clear();
160 }
161 
162 bool
164 {
165  NS_LOG_FUNCTION(this);
166 
167  bool isGenerationTime = false;
168 
169  if (m_controlSlotsEnabled && (m_controlSlotGenerationTime <= Simulator::Now()))
170  {
171  isGenerationTime = true;
172  }
173 
174  return isGenerationTime;
175 }
176 
177 void
179 {
180  NS_LOG_FUNCTION(this);
181 
182  m_controlSlotGenerationTime = Simulator::Now() + offset;
183 }
184 
185 // SatBeamScheduler
186 
187 NS_OBJECT_ENSURE_REGISTERED(SatBeamScheduler);
188 
189 TypeId
191 {
192  static TypeId tid =
193  TypeId("ns3::SatBeamScheduler")
194  .SetParent<Object>()
195  .AddConstructor<SatBeamScheduler>()
196  .AddAttribute("CnoEstimationMode",
197  "Mode of the C/N0 estimator",
198  EnumValue(SatCnoEstimator::LAST),
199  MakeEnumAccessor(&SatBeamScheduler::m_cnoEstimatorMode),
200  MakeEnumChecker(SatCnoEstimator::LAST,
201  "LastValueInWindow",
203  "MinimumValueInWindow",
205  "AverageValueInWindow"))
206  .AddAttribute("CnoEstimationWindow",
207  "Time window for C/N0 estimation.",
208  TimeValue(MilliSeconds(1000)),
209  MakeTimeAccessor(&SatBeamScheduler::m_cnoEstimationWindow),
210  MakeTimeChecker())
211  .AddAttribute("MaxTwoWayPropagationDelay",
212  "Maximum two way propagation delay between GW and UT.",
213  TimeValue(MilliSeconds(560)),
215  MakeTimeChecker())
216  .AddAttribute("MaxTBTPTxAndProcessingDelay",
217  "Maximum TBTP transmission and processing delay at the GW.",
218  TimeValue(MilliSeconds(100)),
220  MakeTimeChecker())
221  .AddAttribute(
222  "ControlSlotsEnabled",
223  "Control slots generation enabled according to ControlSlotInterval attribute.",
224  BooleanValue(false),
225  MakeBooleanAccessor(&SatBeamScheduler::m_controlSlotsEnabled),
226  MakeBooleanChecker())
227  .AddAttribute("ControlSlotInterval",
228  "Time interval to generate time slots for the UT(s).",
229  TimeValue(MilliSeconds(1000)),
230  MakeTimeAccessor(&SatBeamScheduler::m_controlSlotInterval),
231  MakeTimeChecker())
232  .AddAttribute("HandoverStrategy",
233  "Strategy used when performing handover to transfer capacity requests "
234  "and C/No informations",
235  EnumValue(SatBeamScheduler::BASIC),
236  MakeEnumAccessor(&SatBeamScheduler::m_handoverStrategy),
237  MakeEnumChecker(SatBeamScheduler::BASIC,
238  "Basic",
240  "CheckGateway"))
241  .AddAttribute("SuperFrameAllocatorType",
242  "Type of SuperFrameAllocator",
245  MakeEnumChecker(SatEnums::DEFAULT_SUPERFRAME_ALLOCATOR, "Default"))
246  .AddTraceSource("BacklogRequestsTrace",
247  "Trace for backlog requests done to beam scheduler.",
248  MakeTraceSourceAccessor(&SatBeamScheduler::m_backlogRequestsTrace),
249  "ns3::SatBeamScheduler::BacklogRequestsTraceCallback")
250  .AddTraceSource("WaveformTrace",
251  "Trace scheduled wave forms (called once per UT per round).",
252  MakeTraceSourceAccessor(&SatBeamScheduler::m_waveformTrace),
253  "ns3::SatBeamScheduler::WaveformTrace")
254  .AddTraceSource("FrameUtLoadTrace",
255  "Trace UT load per the frame.",
256  MakeTraceSourceAccessor(&SatBeamScheduler::m_frameUtLoadTrace),
257  "ns3::SatFrameUserLoadProbe::FrameUserLoadCallback")
258  .AddTraceSource("FrameLoadTrace",
259  "Trace load per the frame allocated symbols / total symbols.",
260  MakeTraceSourceAccessor(&SatBeamScheduler::m_frameLoadTrace),
261  "ns3::SatFrameSymbolLoadProbe::FrameSymbolLoadCallback")
262  .AddTraceSource("UsableCapacityTrace",
263  "Trace usable capacity per beam in kbps.",
264  MakeTraceSourceAccessor(&SatBeamScheduler::m_usableCapacityTrace),
265  "ns3::SatBeamScheduler::UsableCapacityTraceCallback")
266  .AddTraceSource("UnmetCapacityTrace",
267  "Trace unmet capacity per beam in kbps.",
268  MakeTraceSourceAccessor(&SatBeamScheduler::m_unmetCapacityTrace),
269  "ns3::SatBeamScheduler::UnmetCapacityTrace")
270  .AddTraceSource("ExceedingCapacityTrace",
271  "Trace exceeding capacity per beam in kbps.",
272  MakeTraceSourceAccessor(&SatBeamScheduler::m_exceedingCapacityTrace),
273  "ns3::SatBeamScheduler::ExceedingCapacityTrace");
274  return tid;
275 }
276 
278  : m_beamId(0),
279  m_superframeSeq(0),
281  m_txCallback(),
284  m_maxBbFrameSize(0),
285  m_controlSlotsEnabled(false),
286  m_superframeAllocatorType(SatEnums::DEFAULT_SUPERFRAME_ALLOCATOR),
288 {
289  NS_LOG_FUNCTION(this);
290 }
291 
293 {
294  NS_LOG_FUNCTION(this);
295 }
296 
297 void
299 {
300  NS_LOG_FUNCTION(this);
301  m_txCallback.Nullify();
302  Object::DoDispose();
303 }
304 
305 bool
306 SatBeamScheduler::Send(Ptr<SatControlMessage> msg)
307 {
308  NS_LOG_FUNCTION(this << msg);
309 
310  m_txCallback(msg, Mac48Address::GetBroadcast());
311  return true;
312 }
313 
314 bool
315 SatBeamScheduler::SendTo(Ptr<SatControlMessage> msg, Address utId)
316 {
317  NS_LOG_FUNCTION(this << msg << utId);
318 
319  if (!HasUt(utId))
320  {
321  return false;
322  }
323 
324  m_txCallback(msg, utId);
325  return true;
326 }
327 
328 bool
329 SatBeamScheduler::SendToSatellite(Ptr<SatControlMessage> msg, Address satelliteMac)
330 {
331  NS_LOG_FUNCTION(this << msg << satelliteMac);
332 
333  m_txCallback(msg, satelliteMac);
334  return true;
335 }
336 
337 void
339 {
340  m_txTbtpCallback = cb;
341 }
342 
343 void
346  Ptr<SatSuperframeSeq> seq,
347  uint32_t maxFrameSizeInBytes,
348  Address gwAddress)
349 {
350  NS_LOG_FUNCTION(this << beamId << &cb);
351 
353 
354  m_beamId = beamId;
355  m_txCallback = cb;
356  m_superframeSeq = seq;
357  m_maxBbFrameSize = maxFrameSizeInBytes;
358  m_gwAddress = gwAddress;
359 
367  uint32_t sfCountOffset =
368  (uint32_t)(totalDelay.GetInteger() / seq->GetDuration(0).GetInteger() + 1);
369 
370  // Scheduling starts after one empty super frame.
371  m_superFrameCounter = Singleton<SatRtnLinkTime>::Get()->GetNextSuperFrameCount(
373  sfCountOffset;
374 
380  m_raChRandomIndex = CreateObject<UniformRandomVariable>();
381  m_raChRandomIndex->SetAttribute("Min", DoubleValue(0));
382 
383  // by default we give index 0, even if there is no RA channels configured.
384  uint32_t maxIndex = 0;
385 
387  ->GetRaChannelCount() > 0)
388  {
389  maxIndex = m_superframeSeq->GetSuperframeConf(SatConstVariables::SUPERFRAME_SEQUENCE)
390  ->GetRaChannelCount() -
391  1;
392  }
393 
394  m_raChRandomIndex->SetAttribute("Max", DoubleValue(maxIndex));
395  m_logonChannelIndex = maxIndex + 1;
396 
397  // Create the superframeAllocator object
399  {
401  Ptr<SatDefaultSuperframeAllocator> superframeAllocator =
402  CreateObject<SatDefaultSuperframeAllocator>(
404  m_superframeAllocator = DynamicCast<SatSuperframeAllocator>(superframeAllocator);
405  break;
406  }
407  default: {
408  NS_FATAL_ERROR("Invalid SuperframeAllocatorType");
409  }
410  }
411 
412  NS_LOG_INFO("Initialized SatBeamScheduler");
413 
414  Time delay;
415  Time txTime = Singleton<SatRtnLinkTime>::Get()->GetNextSuperFrameStartTime(
417 
418  if (txTime > Now())
419  {
420  delay = txTime - Now();
421  }
422  else
423  {
424  NS_FATAL_ERROR("Trying to schedule a super frame in the past!");
425  }
426 
427  Simulator::Schedule(delay, &SatBeamScheduler::Schedule, this);
428 }
429 
430 uint32_t
431 SatBeamScheduler::AddUt(Address utId, Ptr<SatLowerLayerServiceConf> llsConf)
432 {
433  NS_LOG_FUNCTION(this << utId);
434 
435  Ptr<SatDamaEntry> damaEntry = Create<SatDamaEntry>(llsConf);
436 
437  Time firstCtrlSlotInterval = m_controlSlotInterval;
438 
441  {
442  Ptr<UniformRandomVariable> m_randomInterval = CreateObject<UniformRandomVariable>();
443  uint32_t randomOffset = m_randomInterval->GetInteger(
444  m_superframeSeq->GetDuration(SatConstVariables::SUPERFRAME_SEQUENCE).GetInteger(),
445  m_controlSlotInterval.GetInteger());
446 
447  firstCtrlSlotInterval = Time(randomOffset);
448  }
449 
450  Ptr<SatCnoEstimator> cnoEstimator = CreateCnoEstimator();
451  Ptr<SatUtInfo> utInfo =
452  Create<SatUtInfo>(damaEntry, cnoEstimator, firstCtrlSlotInterval, m_controlSlotsEnabled);
453  AddUtInfo(utId, utInfo);
454 
455  m_superframeSeq->GetSuperframeConf(SatConstVariables::SUPERFRAME_SEQUENCE)->GetRaChannelCount();
456 
457  // return random RA channel index for the UT.
458  uint32_t raChannel;
459  do
460  {
461  raChannel = m_raChRandomIndex->GetInteger();
462  } while (raChannel == m_logonChannelIndex);
463 
464  return raChannel;
465 }
466 
467 void
468 SatBeamScheduler::AddUtInfo(Address utId, Ptr<SatUtInfo> utInfo)
469 {
470  NS_LOG_FUNCTION(this << utId << utInfo);
471 
472  Ptr<SatDamaEntry> damaEntry = utInfo->GetDamaEntry();
473 
474  // this method call acts as CAC check, if allocation fails fatal error is occurred.
475  m_superframeAllocator->ReserveMinimumRate(
476  damaEntry->GetMinRateBasedBytes(m_superframeAllocator->GetSuperframeDuration()),
478 
479  std::pair<UtInfoMap_t::iterator, bool> result = m_utInfos.insert(std::make_pair(utId, utInfo));
480 
481  if (result.second)
482  {
484  damaEntry->GetRcCount(),
486  SatFrameAllocator::SatFrameAllocReq allocReq(reqContainer);
487  allocReq.m_cno = NAN;
488  allocReq.m_address = utId;
489 
490  m_utRequestInfos.push_back(std::make_pair(utId, allocReq));
491  }
492  else
493  {
494  NS_FATAL_ERROR("UT (Address: " << utId << ") already added to Beam scheduler.");
495  }
496 }
497 
498 void
499 SatBeamScheduler::RemoveUtInfo(UtInfoMap_t::iterator iterator)
500 {
501  Address utId = iterator->first;
502  Ptr<SatUtInfo> utInfo = iterator->second;
503  m_utInfos.erase(iterator);
504 
505  UtReqInfoContainer_t::iterator it = m_utRequestInfos.begin();
506  for (; it != m_utRequestInfos.end(); ++it)
507  {
508  if (it->first == utId)
509  {
510  m_utRequestInfos.erase(it);
511  break;
512  }
513  }
514 
515  Ptr<SatDamaEntry> damaEntry = utInfo->GetDamaEntry();
516  m_superframeAllocator->ReleaseMinimumRate(
517  damaEntry->GetMinRateBasedBytes(m_superframeAllocator->GetSuperframeDuration()),
519 }
520 
521 bool
523 {
524  NS_LOG_FUNCTION(this << utId);
525 
526  UtInfoMap_t::iterator result = m_utInfos.find(utId);
527  return result != m_utInfos.end();
528 }
529 
530 void
531 SatBeamScheduler::UpdateUtCno(Address utId, double cno)
532 {
533  NS_LOG_FUNCTION(this << utId << cno);
534 
535  if (HasUt(utId))
536  {
537  m_utInfos[utId]->AddCnoSample(cno);
538  }
539 }
540 
541 void
542 SatBeamScheduler::UpdateSatelliteCno(Address satelliteMac, double cno)
543 {
544  NS_LOG_FUNCTION(this << satelliteMac << cno);
545 
546  m_satelliteCnoEstimator->AddSample(cno);
547 
548  m_satelliteMac = satelliteMac;
550 }
551 
552 void
553 SatBeamScheduler::UtCrReceived(Address utId, Ptr<SatCrMessage> crMsg)
554 {
555  NS_LOG_FUNCTION(this << utId << crMsg);
556 
557  if (HasUt(utId))
558  {
559  m_utInfos[utId]->AddCrMsg(crMsg);
560  }
561 }
562 
563 Ptr<SatCnoEstimator>
565 {
566  NS_LOG_FUNCTION(this);
567 
568  Ptr<SatCnoEstimator> estimator = NULL;
569 
570  switch (m_cnoEstimatorMode)
571  {
575  estimator = Create<SatBasicCnoEstimator>(m_cnoEstimatorMode, m_cnoEstimationWindow);
576  break;
577 
578  default:
579  NS_FATAL_ERROR("Not supported C/N0 estimation mode!!!");
580  break;
581  }
582 
583  return estimator;
584 }
585 
586 void
588 {
590  {
591  double cno = m_satelliteCnoEstimator->GetCnoEstimation();
592 
593  Ptr<SatCnoReportMessage> cnoReportMessage = CreateObject<SatCnoReportMessage>();
594  cnoReportMessage->SetCnoEstimate(cno);
595 
596  SendToSatellite(cnoReportMessage, m_satelliteMac);
597  }
598 
600 }
601 
602 void
604 {
605  NS_LOG_FUNCTION(this);
606 
607  uint32_t requestedKbpsSum(0);
608  uint32_t offeredKbpsSum(0);
609 
610  // check that there is UTs to schedule
611  if (m_utInfos.size() > 0)
612  {
613  requestedKbpsSum = UpdateDamaEntriesWithReqs();
614 
616 
617  // generate time slots
618  Ptr<SatTbtpMessage> firstTbtp =
619  CreateObject<SatTbtpMessage>(SatConstVariables::SUPERFRAME_SEQUENCE);
620  firstTbtp->SetSuperframeCounter(m_superFrameCounter);
621 
622  std::vector<Ptr<SatTbtpMessage>> tbtps;
623  tbtps.push_back(firstTbtp);
624 
625  // Add RA slots (channels)
626  AddRaChannels(tbtps);
627 
629 
630  // Add DA slots to TBTP(s)
631  m_superframeAllocator->GenerateTimeSlots(tbtps,
633  utAllocs,
637 
638  // update VBDC counter of the UT/RCs
639  offeredKbpsSum += UpdateDamaEntriesWithAllocs(utAllocs);
640 
641  // send TBTPs
642  uint16_t error = 0;
643  for (std::vector<Ptr<SatTbtpMessage>>::const_iterator it = tbtps.begin(); it != tbtps.end();
644  it++)
645  {
646  if ((*it)->GetSizeInBytes() > m_maxBbFrameSize)
647  {
648  ++error;
649  }
650  else
651  {
652  if (!m_txTbtpCallback.IsNull())
653  {
654  m_txTbtpCallback(*it);
655  }
656  Send(*it);
657  }
658  }
659 
660  if (error)
661  {
662  NS_FATAL_ERROR("Too big for " << error << " TBTP messages");
663  }
664 
665  NS_LOG_INFO("TBTP sent");
666  }
667 
668  uint32_t usableCapacity = std::min(offeredKbpsSum, requestedKbpsSum);
669  uint32_t unmetCapacity = requestedKbpsSum - usableCapacity;
670  uint32_t exceedingCapacity =
671  (uint32_t)(std::max(((double)(offeredKbpsSum)-requestedKbpsSum), 0.0) + 0.5);
672  m_usableCapacityTrace(usableCapacity);
673  m_unmetCapacityTrace(unmetCapacity);
674  m_exceedingCapacityTrace(exceedingCapacity);
676 
678 
679  // re-schedule next TBTP sending (call of this function)
680  Simulator::Schedule(m_superframeSeq->GetDuration(SatConstVariables::SUPERFRAME_SEQUENCE),
682  this);
683 }
684 
685 void
686 SatBeamScheduler::AddRaChannels(std::vector<Ptr<SatTbtpMessage>>& tbtpContainer)
687 {
688  NS_LOG_FUNCTION(this);
689 
690  if (tbtpContainer.empty())
691  {
692  NS_FATAL_ERROR("TBTP container must contain at least one message.");
693  }
694 
695  Ptr<SatTbtpMessage> tbtpToFill = tbtpContainer.back();
696 
697  Ptr<SatSuperframeConf> superFrameConf =
699 
700  int32_t prevFrameId = -1;
701 
702  for (uint32_t i = 0; i < superFrameConf->GetRaChannelCount(); i++)
703  {
704  uint8_t frameId = superFrameConf->GetRaChannelFrameId(i);
705  Ptr<SatFrameConf> frameConf = superFrameConf->GetFrameConf(frameId);
706  uint16_t timeSlotCount = frameConf->GetTimeSlotCount() / frameConf->GetCarrierCount();
707 
708  // In case of carrier belong to same frame than previous we don't need to check
709  // size for frame info when adding slot to TBTP, so it is set to 0.
710  uint32_t frameInfoSize = 0;
711 
712  if (prevFrameId != (int32_t)frameId)
713  {
714  // frame changes, so check size needed for frame info in TBTP too
715  frameInfoSize = tbtpToFill->GetFrameInfoSize();
716  }
717 
718  while (timeSlotCount > 0)
719  {
720  // Get max nb of time slots in this TBTP
721  uint32_t timeSlotCountMaxFrame =
722  (m_maxBbFrameSize - tbtpToFill->GetSizeInBytes() - frameInfoSize) /
723  tbtpToFill->GetTimeSlotInfoSizeInBytes();
724  if (timeSlotCountMaxFrame > timeSlotCount)
725  {
726  timeSlotCountMaxFrame = timeSlotCount;
727  }
728 
729  tbtpToFill->SetRaChannel(i,
730  superFrameConf->GetRaChannelFrameId(i),
731  timeSlotCountMaxFrame);
732  timeSlotCount -= timeSlotCountMaxFrame;
733 
734  // if still room, create new tbtp and do it again
735  if (timeSlotCount > 0)
736  {
737  Ptr<SatTbtpMessage> newTbtp =
738  CreateObject<SatTbtpMessage>(tbtpToFill->GetSuperframeSeqId());
739  newTbtp->SetSuperframeCounter(tbtpToFill->GetSuperframeCounter());
740  tbtpContainer.push_back(newTbtp);
741  tbtpToFill = newTbtp;
742  }
743  }
744  }
745 }
746 
747 uint32_t
749 {
750  NS_LOG_FUNCTION(this);
751 
752  uint32_t requestedCraRbdcKbps(0);
753 
754  for (UtReqInfoContainer_t::iterator it = m_utRequestInfos.begin(); it != m_utRequestInfos.end();
755  it++)
756  {
757  // estimation of the C/N0 is done when scheduling UT
758  Ptr<SatDamaEntry> damaEntry = m_utInfos.at(it->first)->GetDamaEntry();
759 
760  // process received CRs
761  m_utInfos.at(it->first)->UpdateDamaEntryFromCrs();
762 
763  // update allocation request information to be used later to request capacity from frame
764  // allocator
765  it->second.m_cno = m_utInfos.at(it->first)->GetCnoEstimation();
766 
767  // set control slot generation on or off
768  it->second.m_generateCtrlSlot = m_utInfos.at(it->first)->IsControlSlotGenerationTime();
769 
770  for (uint8_t i = 0; i < damaEntry->GetRcCount(); i++)
771  {
772  double superFrameDurationInSeconds =
774  ->GetDuration()
775  .GetSeconds();
776 
777  it->second.m_reqPerRc[i].m_craBytes =
778  (SatConstVariables::BITS_IN_KBIT * damaEntry->GetCraInKbps(i) *
779  superFrameDurationInSeconds) /
781  it->second.m_reqPerRc[i].m_rbdcBytes =
782  (SatConstVariables::BITS_IN_KBIT * damaEntry->GetRbdcInKbps(i) *
783  superFrameDurationInSeconds) /
785  it->second.m_reqPerRc[i].m_vbdcBytes = damaEntry->GetVbdcInBytes(i);
786 
787  // Collect the requested rate for all UTs per beam
788  requestedCraRbdcKbps += damaEntry->GetCraInKbps(i);
789  requestedCraRbdcKbps += damaEntry->GetRbdcInKbps(i);
790 
791  uint16_t minRbdcCraDeltaRateInKbps =
792  std::max(0, damaEntry->GetMinRbdcInKbps(i) - damaEntry->GetCraInKbps(i));
793  it->second.m_reqPerRc[i].m_minRbdcBytes =
794  (SatConstVariables::BITS_IN_KBIT * minRbdcCraDeltaRateInKbps *
795  superFrameDurationInSeconds) /
797 
798  // if UT is not requesting any RBDC for this RC then set minimum RBDC 0
799  // This means that no RBDC is actively requested for this RC
800  if (it->second.m_reqPerRc[i].m_rbdcBytes == 0)
801  {
802  it->second.m_reqPerRc[i].m_minRbdcBytes = 0;
803  }
804 
805  NS_ASSERT(
806  (it->second.m_reqPerRc[i].m_minRbdcBytes <= it->second.m_reqPerRc[i].m_rbdcBytes));
807 
808  // it->second.m_reqPerRc[i].m_rbdcBytes =
809  // std::max(it->second.m_reqPerRc[i].m_minRbdcBytes,
810  // it->second.m_reqPerRc[i].m_rbdcBytes);
811 
812  // write backlog requests traces starts ...
813  std::stringstream head;
814  head << Now().GetSeconds() << ", ";
815  head << m_beamId << ", ";
816  head << Singleton<SatIdMapper>::Get()->GetUtIdWithMac(it->first) << ", ";
817 
818  std::stringstream rbdcTail;
819  rbdcTail << SatEnums::DA_RBDC << ", ";
820  rbdcTail << damaEntry->GetRbdcInKbps(i);
821 
822  m_backlogRequestsTrace(head.str() + rbdcTail.str());
823 
824  std::stringstream vbdcTail;
825  vbdcTail << SatEnums::DA_VBDC << ", ";
826  vbdcTail << damaEntry->GetVbdcInBytes(i);
827 
828  m_backlogRequestsTrace(head.str() + vbdcTail.str());
829  // ... write backlog requests traces ends
830  }
831  }
832 
833  return requestedCraRbdcKbps;
834 }
835 
836 void
838 {
839  NS_LOG_FUNCTION(this);
840 
841  if (m_utInfos.size() > 0)
842  {
843  // sort UT requests according to C/N0 of the UTs
845 
847 
848  for (UtReqInfoContainer_t::iterator it = m_utRequestInfos.begin();
849  it != m_utRequestInfos.end();
850  it++)
851  {
852  allocReqs.push_back(&(it->second));
853  }
854 
855  // request capacity for UTs from frame allocator
856  m_superframeAllocator->PreAllocateSymbols(allocReqs);
857  }
858 }
859 
860 uint32_t
863 {
864  NS_LOG_FUNCTION(this);
865 
866  uint32_t offeredCraRbdcKbps(0);
867 
868  for (UtReqInfoContainer_t::iterator it = m_utRequestInfos.begin(); it != m_utRequestInfos.end();
869  it++)
870  {
871  Ptr<SatDamaEntry> damaEntry = m_utInfos.at(it->first)->GetDamaEntry();
872  SatFrameAllocator::UtAllocInfoContainer_t::const_iterator allocInfo =
873  utAllocContainer.find(it->first);
874 
875  if (allocInfo != utAllocContainer.end())
876  {
877  // update time to send next control slot, if control slot is allocated
878  if (allocInfo->second.second)
879  {
880  m_utInfos.at(allocInfo->first)->SetControlSlotGenerationTime(m_controlSlotInterval);
881  }
882 
883  double superFrameDurationInSeconds =
885  ->GetDuration()
886  .GetSeconds();
887 
888  for (uint32_t i = 0; i < allocInfo->second.first.size(); i++)
889  {
890  uint32_t rateBasedBytes =
891  (SatConstVariables::BITS_IN_KBIT * damaEntry->GetCraInKbps(i) *
892  superFrameDurationInSeconds) /
894  rateBasedBytes += (SatConstVariables::BITS_IN_KBIT * damaEntry->GetRbdcInKbps(i) *
895  superFrameDurationInSeconds) /
897 
898  offeredCraRbdcKbps += (uint32_t)((allocInfo->second.first[i] *
900  superFrameDurationInSeconds /
902  0.5);
903 
904  NS_LOG_INFO("UT: " << allocInfo->first << " RC index: " << i
905  << " rate based bytes: " << rateBasedBytes
906  << " allocated bytes: " << allocInfo->second.first[i]);
907 
908  // The scheduler has allocated more than the rate based bytes (CRA+RBDC)
909  if (rateBasedBytes < allocInfo->second.first[i])
910  {
911  // Requested VBDC
912  uint32_t vbdcBytes = damaEntry->GetVbdcInBytes(i);
913 
914  NS_LOG_INFO("UT: " << allocInfo->first << " RC index: " << i
915  << " requested VBDC bytes: " << vbdcBytes);
916 
917  // Allocated VBDC for this RC index
918  uint32_t allocVbdcBytes = allocInfo->second.first[i] - rateBasedBytes;
919 
920  // Allocated less than requested
921  if (vbdcBytes > allocVbdcBytes)
922  {
923  uint32_t remainingVbdcBytes = vbdcBytes - allocVbdcBytes;
924 
925  NS_LOG_INFO("UT: " << allocInfo->first << " RC index: " << i
926  << " VBDC allocation: " << allocVbdcBytes
927  << " remaining VBDC bytes: " << remainingVbdcBytes);
928 
929  damaEntry->SetVbdcInBytes(i, remainingVbdcBytes);
930  }
931  // Allocated more or equal to requested bytes
932  else
933  {
934  NS_LOG_INFO("UT: " << allocInfo->first << " RC index: " << i
935  << " VBDC allocation: " << allocVbdcBytes
936  << " remaining VBDC bytes: " << 0);
937 
938  damaEntry->SetVbdcInBytes(i, 0);
939  }
940  }
941  }
942  }
943  // decrease persistence values
944  damaEntry->DecrementDynamicRatePersistence();
945  damaEntry->DecrementVolumeBacklogPersistence();
946  }
947  return offeredCraRbdcKbps;
948 }
949 
950 void
951 SatBeamScheduler::TransferUtToBeam(Address utId, Ptr<SatBeamScheduler> destination)
952 {
953  NS_LOG_FUNCTION(this << utId << destination->m_beamId);
954 
955  UtInfoMap_t::iterator utIterator = m_utInfos.find(utId);
956  if (utIterator == m_utInfos.end())
957  {
958  // Check if handover already happened
959  NS_ASSERT_MSG(destination->HasUt(utId), "UT is not part of the source beam");
960  }
961  else
962  {
963  // Moving UT infos between beams
964  Ptr<SatUtInfo> utInfo = utIterator->second;
965  destination->AddUtInfo(utId, utInfo);
966  RemoveUtInfo(utIterator);
967 
968  // Handling capacity requests left and C/No estimations
969  switch (m_handoverStrategy)
970  {
971  case BASIC: {
972  utInfo->ClearCrMsgs();
973  break;
974  }
975  case CHECK_GATEWAY: {
976  if (m_gwAddress != destination->m_gwAddress)
977  {
978  utInfo->ClearCrMsgs();
979  }
980  break;
981  }
982  default:
983  NS_FATAL_ERROR("Unknown handover strategy");
984  }
985  }
986 }
987 
988 void
990 {
991  NS_LOG_FUNCTION(this << utId);
992 
993  UtInfoMap_t::iterator utIterator = m_utInfos.find(utId);
994  if (utIterator == m_utInfos.end())
995  {
996  NS_FATAL_ERROR("Trying to remove a UT not connected to a beam: " << utId);
997  }
998 
999  // Moving UT infos between beams
1000  Ptr<SatUtInfo> utInfo = utIterator->second;
1001  RemoveUtInfo(utIterator);
1002 }
1003 
1004 Ptr<SatTimuMessage>
1006 {
1007  NS_LOG_FUNCTION(this);
1008 
1009  Ptr<SatTimuMessage> timuMsg = CreateObject<SatTimuMessage>();
1010  timuMsg->SetAllocatedBeamId(m_beamId);
1011  timuMsg->SetGwAddress(m_gwAddress);
1012  return timuMsg;
1013 }
1014 
1015 void
1017 {
1018  NS_LOG_FUNCTION(this << logonChannelId);
1019 
1020  DoubleValue maxId;
1021  m_raChRandomIndex->GetAttribute("Max", maxId);
1022  uint32_t maxIndex = maxId.Get();
1023 
1024  if (logonChannelId > maxIndex)
1025  {
1026  NS_FATAL_ERROR("Cannot use channel ID " << logonChannelId
1027  << " for logon as it doesn't exist");
1028  }
1029 
1030  if (maxIndex != 0)
1031  {
1032  // Allows to still return the channel 0 as the random access
1033  // channel for UTs without entering in an infinite loop in AddUt
1034  m_logonChannelIndex = logonChannelId;
1035  }
1036 }
1037 
1038 } // namespace ns3
CnoCompare class to sort UT request according to C/N0 information.
void ClearCrMsgs()
Remove all CR messages from UT info to reset capacity requests in case of handover.
void UpdateDamaEntryFromCrs()
Update DamaEntry with information of the received CR messages.
void AddCrMsg(Ptr< SatCrMessage > crMsg)
Add CR message to UT info to be used when capacity request is calculated next time (method UpdateDama...
double GetCnoEstimation()
Get estimated C/N0 value based on added samples.
Ptr< SatDamaEntry > GetDamaEntry()
Get damaEntry of the UT info.
bool IsControlSlotGenerationTime() const
Check if time is expired to send control slot.
SatUtInfo(Ptr< SatDamaEntry > damaEntry, Ptr< SatCnoEstimator > cnoEstimator, Time controlSlotOffset, bool controlSlotsEnabled)
Construct SatUtInfo.
void SetControlSlotGenerationTime(Time offset)
Set time for next time slot generation for this UT.
void AddCnoSample(double sample)
Add C/N0 sample to UT info's estimator.
class for module Beam Scheduler.
bool SendToSatellite(Ptr< SatControlMessage > msg, Address satelliteMac)
Send control message to the satellite.
HandoverInformationForward_t m_handoverStrategy
void UtCrReceived(Address utId, Ptr< SatCrMessage > crMsg)
Receive capacity requests from UTs.
uint32_t UpdateDamaEntriesWithAllocs(SatFrameAllocator::UtAllocInfoContainer_t &utAllocContainer)
Update dama entries with given allocations at end of the scheduling.
uint32_t m_maxBbFrameSize
Maximum size of the BB frame.
Ptr< SatCnoEstimator > m_satelliteCnoEstimator
Estimator for the C/N0 from satellite.
Time m_cnoEstimationWindow
Time window for C/N0 estimation.
bool m_receivedSatelliteCnoSample
Indicates if Cno sample have been received since last C/N0 control message sent.
Callback< bool, Ptr< SatControlMessage >, const Address & > SendCtrlMsgCallback
SatBeamScheduler::SendTbtpCallback m_txTbtpCallback
The TBTP send callback to inform GW Mac.
void AddRaChannels(std::vector< Ptr< SatTbtpMessage >> &tbtpContainer)
Add RA channel information to TBTP(s).
void DoPreResourceAllocation()
Do pre-allocation of the symbols per UT/RC, before time slot generation.
Time m_maxTwoWayPropagationDelay
Maximum two-way propagation delay estimate between GW-SAT-UT-SAT-GW.
void RemoveUtInfo(UtInfoMap_t::iterator iterator)
TracedCallback< uint32_t > m_exceedingCapacityTrace
Trace exceeding capacity.
Callback< void, Ptr< SatTbtpMessage > > SendTbtpCallback
void AddUtInfo(Address utId, Ptr< SatUtInfo > utInfo)
TracedCallback< uint32_t > m_usableCapacityTrace
Trace usable capacity.
TracedCallback< uint32_t, double > m_frameLoadTrace
Trace frame load ratio.
void DoDispose(void)
Dispose actions for SatBeamScheduler.
SatBeamScheduler::SendCtrlMsgCallback m_txCallback
The control message send callback.
uint32_t m_logonChannelIndex
Logon channel ID to exclude it from the RA channel selection.
SatEnums::SuperframeAllocatorType_t m_superframeAllocatorType
Type of SatSuperframeAllocator class to use.
void SetSendTbtpCallback(SendTbtpCallback cb)
Set the callback to inform NCC a TBTP has been sent.
Time m_controlSlotInterval
Interval to generate control time slots.
bool Send(Ptr< SatControlMessage > message)
Send control messages to the beam.
bool SendTo(Ptr< SatControlMessage > message, Address utId)
Send control message to an UT into the beam.
Ptr< SatSuperframeSeq > m_superframeSeq
Pointer to super frame sequence.
Ptr< SatCnoEstimator > CreateCnoEstimator()
Create estimator for the UT according to set attributes.
Ptr< SatSuperframeAllocator > m_superframeAllocator
Superframe allocator to maintain load information of the frames and their configurations.
TracedCallback< std::string > m_backlogRequestsTrace
Trace for backlog requests done to beam scheduler.
TracedCallback< uint32_t, uint32_t > m_frameUtLoadTrace
Trace count of UTs scheduled per Frame.
TracedCallback< uint32_t > m_waveformTrace
Trace first wave form scheduled for the UT.
Ptr< RandomVariableStream > m_raChRandomIndex
Random variable stream to select RA channel for a UT.
static TypeId GetTypeId(void)
Get the type ID.
Time m_maxTbtpTxAndProcessingDelay
Maximum TBTP tx and processing delay estimate at the GW (scheduler).
void SendCnoToSatellite()
Send an estimation of cno to satellite, if samples have been received.
void TransferUtToBeam(Address utId, Ptr< SatBeamScheduler > destination)
Transfer ownership of a terminal to the given SatBeamScheduler.
void ReserveLogonChannel(uint32_t logonChannelId)
~SatBeamScheduler()
Destroy a SatBeamScheduler.
bool HasUt(Address utId)
Check whether an UT is handled by this scheduler.
uint32_t m_superFrameCounter
Counter for super frame sequence.
Ptr< SatTimuMessage > CreateTimu() const
Create a TIM unicast message containing enough data for a terminal to connect to the beam handled by ...
void RemoveUt(Address utId)
Remove a UT from its SatBeamScheduler.
void Initialize(uint32_t beamId, SatBeamScheduler::SendCtrlMsgCallback cb, Ptr< SatSuperframeSeq > seq, uint32_t maxFrameSizeInBytes, Address gwAddress)
UtReqInfoContainer_t m_utRequestInfos
Container including every UT's allocation requests.
Address m_satelliteMac
MAC address of the satellite (used when regenerative)
SatCnoEstimator::EstimationMode_t m_cnoEstimatorMode
Mode used for C/N0 estimator.
void Schedule()
Schedule UTs added (registered) to scheduler.
bool m_controlSlotsEnabled
Flag to indicated if control time slots generation is enabled.
uint32_t m_beamId
ID of the beam.
uint32_t UpdateDamaEntriesWithReqs()
Update dama entries with received requests at beginning of the scheduling.
void UpdateUtCno(Address utId, double cno)
Update UT C/N0 info with the latest value.
SatBeamScheduler()
Construct a SatBeamScheduler.
uint32_t AddUt(Address utId, Ptr< SatLowerLayerServiceConf > llsConf)
Add UT to scheduler.
UtInfoMap_t m_utInfos
Map to store UT information in beam for updating purposes.
void UpdateSatelliteCno(Address satelliteMac, double cno)
Update satellite C/N0 info with the latest value.
TracedCallback< uint32_t > m_unmetCapacityTrace
Trace unmet capacity.
SatCnoEstimator class defines interface for C/N0 estimators.
@ MINIMUM
Minimum value in the given window returned.
@ LAST
Last value in the given window returned.
@ AVERAGE
Average value in the given window returned.
std::map< RequestDescriptor_t, uint16_t > RequestContainer_t
Define type RequestContainer_t.
SatEnums class is for simplifying the use of enumerators in the satellite module.
SatFrameAllocReq is used to define frame allocation parameters when requesting allocation from SatFra...
Allocation information item for the UT/RC requests [bytes].
std::vector< SatFrameAllocReq * > SatFrameAllocContainer_t
Container to store SatFrameAllocReq item pointers.
std::map< Address, UtAllocInfoItem_t > UtAllocInfoContainer_t
Map container to store UT allocation information.
std::vector< SatFrameAllocReqItem > SatFrameAllocReqItemContainer_t
Container to store SatFrameAllocReqItem items.
constexpr uint8_t SUPERFRAME_SEQUENCE
Used superframe sequence in the RTN link.
constexpr uint32_t BITS_IN_KBIT
Number of bits consisting a kilobit.
constexpr uint32_t BITS_PER_BYTE
Number of bits in a byte.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.