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 <map>
48 #include <sstream>
49 #include <utility>
50 #include <vector>
51 
52 NS_LOG_COMPONENT_DEFINE("SatBeamScheduler");
53 
54 namespace ns3
55 {
56 
57 // UtInfo class declarations for SatBeamScheduler
58 SatBeamScheduler::SatUtInfo::SatUtInfo(Ptr<SatDamaEntry> damaEntry,
59  Ptr<SatCnoEstimator> cnoEstimator,
60  Time controlSlotOffset,
61  bool controlSlotsEnabled)
62  : m_damaEntry(damaEntry),
63  m_cnoEstimator(cnoEstimator),
64  m_controlSlotsEnabled(controlSlotsEnabled)
65 {
66  NS_LOG_FUNCTION(this);
67 
68  SetControlSlotGenerationTime(controlSlotOffset);
69 }
70 
71 Ptr<SatDamaEntry>
73 {
74  NS_LOG_FUNCTION(this);
75 
76  return m_damaEntry;
77 }
78 
79 void
81 {
82  NS_LOG_FUNCTION(this);
83 
84  // map to sum up RBDC requests per RC
85  std::map<uint8_t, uint16_t> rbdcReqs;
86 
87  for (CrMsgContainer_t::const_iterator crIt = m_crContainer.begin(); crIt != m_crContainer.end();
88  crIt++)
89  {
90  SatCrMessage::RequestContainer_t crContent = (*crIt)->GetCapacityRequestContent();
91 
92  for (SatCrMessage::RequestContainer_t::const_iterator descriptorIt = crContent.begin();
93  descriptorIt != crContent.end();
94  descriptorIt++)
95  {
96  switch (descriptorIt->first.second)
97  {
98  case SatEnums::DA_RBDC: {
99  rbdcReqs[descriptorIt->first.first] += descriptorIt->second;
100  break;
101  }
102 
103  case SatEnums::DA_VBDC: {
104  m_damaEntry->ResetVolumeBacklogPersistence();
105  m_damaEntry->UpdateVbdcInBytes(descriptorIt->first.first, descriptorIt->second);
106  break;
107  }
108 
109  case SatEnums::DA_AVBDC: {
110  m_damaEntry->ResetVolumeBacklogPersistence();
111  m_damaEntry->SetVbdcInBytes(descriptorIt->first.first, descriptorIt->second);
112  break;
113  }
114 
115  default:
116  break;
117  }
118  }
119  }
120 
121  // update RBDC with summed up requests
122  for (std::map<uint8_t, uint16_t>::iterator it = rbdcReqs.begin(); it != rbdcReqs.end(); it++)
123  {
124  m_damaEntry->ResetDynamicRatePersistence();
125  m_damaEntry->UpdateRbdcInKbps(it->first, it->second);
126  }
127 
128  // clear container when CRs processed
129  m_crContainer.clear();
130 }
131 
132 double
134 {
135  NS_LOG_FUNCTION(this);
136 
137  return m_cnoEstimator->GetCnoEstimation();
138 }
139 
140 void
142 {
143  NS_LOG_FUNCTION(this << sample);
144 
145  m_cnoEstimator->AddSample(sample);
146 }
147 
148 void
150 {
151  NS_LOG_FUNCTION(this << crMsg);
152 
153  m_crContainer.push_back(crMsg);
154 }
155 
156 void
158 {
159  NS_LOG_FUNCTION(this);
160 
161  m_crContainer.clear();
162 }
163 
164 bool
166 {
167  NS_LOG_FUNCTION(this);
168 
169  bool isGenerationTime = false;
170 
171  if (m_controlSlotsEnabled && (m_controlSlotGenerationTime <= Simulator::Now()))
172  {
173  isGenerationTime = true;
174  }
175 
176  return isGenerationTime;
177 }
178 
179 void
181 {
182  NS_LOG_FUNCTION(this);
183 
184  m_controlSlotGenerationTime = Simulator::Now() + offset;
185 }
186 
187 // SatBeamScheduler
188 
189 NS_OBJECT_ENSURE_REGISTERED(SatBeamScheduler);
190 
191 TypeId
193 {
194  static TypeId tid =
195  TypeId("ns3::SatBeamScheduler")
196  .SetParent<Object>()
197  .AddConstructor<SatBeamScheduler>()
198  .AddAttribute("CnoEstimationMode",
199  "Mode of the C/N0 estimator",
200  EnumValue(SatCnoEstimator::LAST),
201  MakeEnumAccessor<SatCnoEstimator::EstimationMode_t>(
203  MakeEnumChecker(SatCnoEstimator::LAST,
204  "LastValueInWindow",
206  "MinimumValueInWindow",
208  "AverageValueInWindow"))
209  .AddAttribute("CnoEstimationWindow",
210  "Time window for C/N0 estimation.",
211  TimeValue(MilliSeconds(1000)),
212  MakeTimeAccessor(&SatBeamScheduler::m_cnoEstimationWindow),
213  MakeTimeChecker())
214  .AddAttribute("MaxTwoWayPropagationDelay",
215  "Maximum two way propagation delay between GW and UT.",
216  TimeValue(MilliSeconds(560)),
218  MakeTimeChecker())
219  .AddAttribute("MaxTBTPTxAndProcessingDelay",
220  "Maximum TBTP transmission and processing delay at the GW.",
221  TimeValue(MilliSeconds(100)),
223  MakeTimeChecker())
224  .AddAttribute(
225  "ControlSlotsEnabled",
226  "Control slots generation enabled according to ControlSlotInterval attribute.",
227  BooleanValue(false),
228  MakeBooleanAccessor(&SatBeamScheduler::m_controlSlotsEnabled),
229  MakeBooleanChecker())
230  .AddAttribute("ControlSlotInterval",
231  "Time interval to generate time slots for the UT(s).",
232  TimeValue(MilliSeconds(1000)),
233  MakeTimeAccessor(&SatBeamScheduler::m_controlSlotInterval),
234  MakeTimeChecker())
235  .AddAttribute("HandoverStrategy",
236  "Strategy used when performing handover to transfer capacity requests "
237  "and C/No informations",
238  EnumValue(SatBeamScheduler::BASIC),
239  MakeEnumAccessor<SatBeamScheduler::HandoverInformationForward_t>(
241  MakeEnumChecker(SatBeamScheduler::BASIC,
242  "Basic",
244  "CheckGateway"))
245  .AddAttribute("SuperFrameAllocatorType",
246  "Type of SuperFrameAllocator",
248  MakeEnumAccessor<SatEnums::SuperframeAllocatorType_t>(
250  MakeEnumChecker(SatEnums::DEFAULT_SUPERFRAME_ALLOCATOR, "Default"))
251  .AddTraceSource("BacklogRequestsTrace",
252  "Trace for backlog requests done to beam scheduler.",
253  MakeTraceSourceAccessor(&SatBeamScheduler::m_backlogRequestsTrace),
254  "ns3::SatBeamScheduler::BacklogRequestsTraceCallback")
255  .AddTraceSource("WaveformTrace",
256  "Trace scheduled wave forms (called once per UT per round).",
257  MakeTraceSourceAccessor(&SatBeamScheduler::m_waveformTrace),
258  "ns3::SatBeamScheduler::WaveformTrace")
259  .AddTraceSource("FrameUtLoadTrace",
260  "Trace UT load per the frame.",
261  MakeTraceSourceAccessor(&SatBeamScheduler::m_frameUtLoadTrace),
262  "ns3::SatFrameUserLoadProbe::FrameUserLoadCallback")
263  .AddTraceSource("FrameLoadTrace",
264  "Trace load per the frame allocated symbols / total symbols.",
265  MakeTraceSourceAccessor(&SatBeamScheduler::m_frameLoadTrace),
266  "ns3::SatFrameSymbolLoadProbe::FrameSymbolLoadCallback")
267  .AddTraceSource("UsableCapacityTrace",
268  "Trace usable capacity per beam in kbps.",
269  MakeTraceSourceAccessor(&SatBeamScheduler::m_usableCapacityTrace),
270  "ns3::SatBeamScheduler::UsableCapacityTraceCallback")
271  .AddTraceSource("UnmetCapacityTrace",
272  "Trace unmet capacity per beam in kbps.",
273  MakeTraceSourceAccessor(&SatBeamScheduler::m_unmetCapacityTrace),
274  "ns3::SatBeamScheduler::UnmetCapacityTrace")
275  .AddTraceSource("ExceedingCapacityTrace",
276  "Trace exceeding capacity per beam in kbps.",
277  MakeTraceSourceAccessor(&SatBeamScheduler::m_exceedingCapacityTrace),
278  "ns3::SatBeamScheduler::ExceedingCapacityTrace");
279  return tid;
280 }
281 
283  : m_satId(0),
284  m_beamId(0),
285  m_superframeSeq(0),
287  m_txCallback(),
290  m_maxBbFrameSize(0),
291  m_controlSlotsEnabled(false),
292  m_superframeAllocatorType(SatEnums::DEFAULT_SUPERFRAME_ALLOCATOR),
294 {
295  NS_LOG_FUNCTION(this);
296 }
297 
299 {
300  NS_LOG_FUNCTION(this);
301 }
302 
303 void
305 {
306  NS_LOG_FUNCTION(this);
307  m_txCallback.Nullify();
308  Object::DoDispose();
309 }
310 
311 bool
312 SatBeamScheduler::Send(Ptr<SatControlMessage> msg)
313 {
314  NS_LOG_FUNCTION(this << msg);
315 
316  m_txCallback(msg, Mac48Address::GetBroadcast());
317  return true;
318 }
319 
320 bool
321 SatBeamScheduler::SendTo(Ptr<SatControlMessage> msg, Address utId)
322 {
323  NS_LOG_FUNCTION(this << msg << utId);
324 
325  if (!HasUt(utId))
326  {
327  return false;
328  }
329 
330  m_txCallback(msg, utId);
331  return true;
332 }
333 
334 bool
335 SatBeamScheduler::SendToSatellite(Ptr<SatControlMessage> msg, Address satelliteMac)
336 {
337  NS_LOG_FUNCTION(this << msg << satelliteMac);
338 
339  m_txCallback(msg, satelliteMac);
340  return true;
341 }
342 
343 void
345 {
346  NS_LOG_FUNCTION(this << &cb);
347 
348  m_txTbtpCallback = cb;
349 }
350 
351 void
353  uint32_t beamId,
354  Ptr<SatNetDevice> gwNetDevice,
355  Ptr<SatOrbiterNetDevice> orbiterNetDevice,
357  Ptr<SatSuperframeSeq> seq,
358  uint32_t maxFrameSizeInBytes,
359  Address satAddress,
360  Address gwAddress)
361 {
362  NS_LOG_FUNCTION(this << beamId << &cb);
363 
365 
366  m_satId = satId;
367  m_beamId = beamId;
368  m_gwMac = DynamicCast<SatGwMac>(gwNetDevice->GetMac());
369  m_orbiterNetDevice = orbiterNetDevice;
370  m_txCallback = cb;
371  m_superframeSeq = seq;
372  m_maxBbFrameSize = maxFrameSizeInBytes;
373  m_satAddress = satAddress;
374  m_gwAddress = gwAddress;
375 
383  uint32_t sfCountOffset =
384  (uint32_t)(totalDelay.GetInteger() / seq->GetDuration(0).GetInteger() + 1);
385 
386  // Scheduling starts after one empty super frame.
387  m_superFrameCounter = Singleton<SatRtnLinkTime>::Get()->GetNextSuperFrameCount(
389  sfCountOffset;
390 
396  m_raChRandomIndex = CreateObject<UniformRandomVariable>();
397  m_raChRandomIndex->SetAttribute("Min", DoubleValue(0));
398 
399  // by default we give index 0, even if there is no RA channels configured.
400  uint32_t maxIndex = 0;
401 
403  ->GetRaChannelCount() > 0)
404  {
405  maxIndex = m_superframeSeq->GetSuperframeConf(SatConstVariables::SUPERFRAME_SEQUENCE)
406  ->GetRaChannelCount() -
407  1;
408  }
409 
410  m_raChRandomIndex->SetAttribute("Max", DoubleValue(maxIndex));
411  m_logonChannelIndex = maxIndex + 1;
412 
413  // Create the superframeAllocator object
415  {
417  Ptr<SatDefaultSuperframeAllocator> superframeAllocator =
418  CreateObject<SatDefaultSuperframeAllocator>(
420  m_superframeAllocator = DynamicCast<SatSuperframeAllocator>(superframeAllocator);
421  break;
422  }
423  default: {
424  NS_FATAL_ERROR("Invalid SuperframeAllocatorType");
425  }
426  }
427 
428  NS_LOG_INFO("Initialized SatBeamScheduler");
429 
430  Time delay;
431  Time txTime = Singleton<SatRtnLinkTime>::Get()->GetNextSuperFrameStartTime(
433 
434  if (txTime > Now())
435  {
436  delay = txTime - Now();
437  }
438  else
439  {
440  NS_FATAL_ERROR("Trying to schedule a super frame in the past!");
441  }
442 
443  Simulator::Schedule(delay, &SatBeamScheduler::Schedule, this);
444 }
445 
446 uint32_t
447 SatBeamScheduler::AddUt(Address utId, Ptr<SatLowerLayerServiceConf> llsConf)
448 {
449  NS_LOG_FUNCTION(this << utId);
450 
451  Ptr<SatDamaEntry> damaEntry = Create<SatDamaEntry>(llsConf);
452 
453  Time firstCtrlSlotInterval = m_controlSlotInterval;
454 
457  {
458  Ptr<UniformRandomVariable> m_randomInterval = CreateObject<UniformRandomVariable>();
459  uint32_t randomOffset = m_randomInterval->GetInteger(
460  m_superframeSeq->GetDuration(SatConstVariables::SUPERFRAME_SEQUENCE).GetInteger(),
461  m_controlSlotInterval.GetInteger());
462 
463  firstCtrlSlotInterval = Time(randomOffset);
464  }
465 
466  Ptr<SatCnoEstimator> cnoEstimator = CreateCnoEstimator();
467  Ptr<SatUtInfo> utInfo =
468  Create<SatUtInfo>(damaEntry, cnoEstimator, firstCtrlSlotInterval, m_controlSlotsEnabled);
469  AddUtInfo(utId, utInfo);
470 
471  m_superframeSeq->GetSuperframeConf(SatConstVariables::SUPERFRAME_SEQUENCE)->GetRaChannelCount();
472 
473  // return random RA channel index for the UT.
474  uint32_t raChannel;
475  do
476  {
477  raChannel = m_raChRandomIndex->GetInteger();
478  } while (raChannel == m_logonChannelIndex);
479 
480  return raChannel;
481 }
482 
483 void
484 SatBeamScheduler::AddUtInfo(Address utId, Ptr<SatUtInfo> utInfo)
485 {
486  NS_LOG_FUNCTION(this << utId << utInfo);
487 
488  Ptr<SatDamaEntry> damaEntry = utInfo->GetDamaEntry();
489 
490  // this method call acts as CAC check, if allocation fails fatal error is occurred.
491  m_superframeAllocator->ReserveMinimumRate(
492  damaEntry->GetMinRateBasedBytes(m_superframeAllocator->GetSuperframeDuration()),
494 
495  std::pair<UtInfoMap_t::iterator, bool> result = m_utInfos.insert(std::make_pair(utId, utInfo));
496 
497  if (result.second)
498  {
500  damaEntry->GetRcCount(),
502  SatFrameAllocator::SatFrameAllocReq allocReq(reqContainer);
503  allocReq.m_cno = NAN;
504  allocReq.m_address = utId;
505 
506  m_utRequestInfos.push_back(std::make_pair(utId, allocReq));
507  }
508  else
509  {
510  NS_FATAL_ERROR("UT (Address: " << utId << ") already added to Beam scheduler.");
511  }
512 }
513 
514 void
515 SatBeamScheduler::RemoveUtInfo(UtInfoMap_t::iterator iterator)
516 {
517  Address utId = iterator->first;
518  Ptr<SatUtInfo> utInfo = iterator->second;
519  m_utInfos.erase(iterator);
520 
521  UtReqInfoContainer_t::iterator it = m_utRequestInfos.begin();
522  for (; it != m_utRequestInfos.end(); ++it)
523  {
524  if (it->first == utId)
525  {
526  m_utRequestInfos.erase(it);
527  break;
528  }
529  }
530 
531  Ptr<SatDamaEntry> damaEntry = utInfo->GetDamaEntry();
532  m_superframeAllocator->ReleaseMinimumRate(
533  damaEntry->GetMinRateBasedBytes(m_superframeAllocator->GetSuperframeDuration()),
535 }
536 
537 bool
539 {
540  NS_LOG_FUNCTION(this << utId);
541 
542  UtInfoMap_t::iterator result = m_utInfos.find(utId);
543  return result != m_utInfos.end();
544 }
545 
546 bool
548 {
549  NS_LOG_FUNCTION(this);
550 
551  return !m_utInfos.empty();
552 }
553 
554 void
555 SatBeamScheduler::UpdateUtCno(Address utId, double cno)
556 {
557  NS_LOG_FUNCTION(this << utId << cno);
558 
559  if (HasUt(utId))
560  {
561  m_utInfos[utId]->AddCnoSample(cno);
562  }
563 }
564 
565 void
566 SatBeamScheduler::UpdateSatelliteCno(Address satelliteMac, double cno)
567 {
568  NS_LOG_FUNCTION(this << satelliteMac << cno);
569 
570  m_satelliteCnoEstimator->AddSample(cno);
571 
572  m_satelliteMac = satelliteMac;
574 }
575 
576 void
577 SatBeamScheduler::UtCrReceived(Address utId, Ptr<SatCrMessage> crMsg)
578 {
579  NS_LOG_FUNCTION(this << utId << crMsg);
580 
581  if (HasUt(utId))
582  {
583  m_utInfos[utId]->AddCrMsg(crMsg);
584  }
585 }
586 
587 Ptr<SatCnoEstimator>
589 {
590  NS_LOG_FUNCTION(this);
591 
592  Ptr<SatCnoEstimator> estimator = nullptr;
593 
594  switch (m_cnoEstimatorMode)
595  {
599  estimator = Create<SatBasicCnoEstimator>(m_cnoEstimatorMode, m_cnoEstimationWindow);
600  break;
601 
602  default:
603  NS_FATAL_ERROR("Not supported C/N0 estimation mode!!!");
604  break;
605  }
606 
607  return estimator;
608 }
609 
610 void
612 {
614  {
615  double cno = m_satelliteCnoEstimator->GetCnoEstimation();
616 
617  Ptr<SatCnoReportMessage> cnoReportMessage = CreateObject<SatCnoReportMessage>();
618  cnoReportMessage->SetCnoEstimate(cno);
619 
620  SendToSatellite(cnoReportMessage, m_satelliteMac);
621  }
622 
624 }
625 
626 void
628 {
629  NS_LOG_FUNCTION(this);
630 
631  uint32_t requestedKbpsSum(0);
632  uint32_t offeredKbpsSum(0);
633 
634  if (m_useLora)
635  {
636  return;
637  }
638 
639  // check that there is UTs to schedule
640  if (m_utInfos.size() > 0 && !m_useLora)
641  {
642  requestedKbpsSum = UpdateDamaEntriesWithReqs();
643 
645 
646  // generate time slots
647  Ptr<SatTbtpMessage> firstTbtp =
648  CreateObject<SatTbtpMessage>(SatConstVariables::SUPERFRAME_SEQUENCE);
649  firstTbtp->SetSuperframeCounter(m_superFrameCounter);
650 
651  std::vector<Ptr<SatTbtpMessage>> tbtps;
652  tbtps.push_back(firstTbtp);
653 
654  // Add RA slots (channels)
655  AddRaChannels(tbtps);
656 
658 
659  // Add DA slots to TBTP(s)
660  m_superframeAllocator->GenerateTimeSlots(tbtps,
662  utAllocs,
666 
667  // update VBDC counter of the UT/RCs
668  offeredKbpsSum += UpdateDamaEntriesWithAllocs(utAllocs);
669 
670  // send TBTPs
671  uint16_t error = 0;
672  for (std::vector<Ptr<SatTbtpMessage>>::const_iterator it = tbtps.begin(); it != tbtps.end();
673  it++)
674  {
675  if ((*it)->GetSizeInBytes() > m_maxBbFrameSize)
676  {
677  ++error;
678  }
679  else
680  {
681  if (!m_txTbtpCallback.IsNull())
682  {
683  m_txTbtpCallback(*it);
684  }
685  Send(*it);
686  }
687  }
688 
689  if (error)
690  {
691  NS_FATAL_ERROR("Too big for " << error << " TBTP messages");
692  }
693 
694  NS_LOG_INFO("TBTP sent");
695  }
696 
697  uint32_t usableCapacity = std::min(offeredKbpsSum, requestedKbpsSum);
698  uint32_t unmetCapacity = requestedKbpsSum - usableCapacity;
699  uint32_t exceedingCapacity =
700  (uint32_t)(std::max(((double)(offeredKbpsSum)-requestedKbpsSum), 0.0) + 0.5);
701  m_usableCapacityTrace(usableCapacity);
702  m_unmetCapacityTrace(unmetCapacity);
703  m_exceedingCapacityTrace(exceedingCapacity);
705 
707 
708  // re-schedule next TBTP sending (call of this function)
709  Simulator::Schedule(m_superframeSeq->GetDuration(SatConstVariables::SUPERFRAME_SEQUENCE),
711  this);
712 }
713 
714 void
715 SatBeamScheduler::AddRaChannels(std::vector<Ptr<SatTbtpMessage>>& tbtpContainer)
716 {
717  NS_LOG_FUNCTION(this);
718 
719  if (tbtpContainer.empty())
720  {
721  NS_FATAL_ERROR("TBTP container must contain at least one message.");
722  }
723 
724  Ptr<SatTbtpMessage> tbtpToFill = tbtpContainer.back();
725 
726  Ptr<SatSuperframeConf> superFrameConf =
728 
729  int32_t prevFrameId = -1;
730 
731  for (uint32_t i = 0; i < superFrameConf->GetRaChannelCount(); i++)
732  {
733  uint8_t frameId = superFrameConf->GetRaChannelFrameId(i);
734  Ptr<SatFrameConf> frameConf = superFrameConf->GetFrameConf(frameId);
735  uint16_t timeSlotCount = frameConf->GetTimeSlotCount() / frameConf->GetCarrierCount();
736 
737  // In case of carrier belong to same frame than previous we don't need to check
738  // size for frame info when adding slot to TBTP, so it is set to 0.
739  uint32_t frameInfoSize = 0;
740 
741  if (prevFrameId != (int32_t)frameId)
742  {
743  // frame changes, so check size needed for frame info in TBTP too
744  frameInfoSize = tbtpToFill->GetFrameInfoSize();
745  }
746 
747  while (timeSlotCount > 0)
748  {
749  // Get max nb of time slots in this TBTP
750  uint32_t timeSlotCountMaxFrame =
751  (m_maxBbFrameSize - tbtpToFill->GetSizeInBytes() - frameInfoSize) /
752  tbtpToFill->GetTimeSlotInfoSizeInBytes();
753  if (timeSlotCountMaxFrame > timeSlotCount)
754  {
755  timeSlotCountMaxFrame = timeSlotCount;
756  }
757 
758  tbtpToFill->SetRaChannel(i,
759  superFrameConf->GetRaChannelFrameId(i),
760  timeSlotCountMaxFrame);
761  timeSlotCount -= timeSlotCountMaxFrame;
762 
763  // if still room, create new tbtp and do it again
764  if (timeSlotCount > 0)
765  {
766  Ptr<SatTbtpMessage> newTbtp =
767  CreateObject<SatTbtpMessage>(tbtpToFill->GetSuperframeSeqId());
768  newTbtp->SetSuperframeCounter(tbtpToFill->GetSuperframeCounter());
769  tbtpContainer.push_back(newTbtp);
770  tbtpToFill = newTbtp;
771  }
772  }
773  }
774 }
775 
776 uint32_t
778 {
779  NS_LOG_FUNCTION(this);
780 
781  uint32_t requestedCraRbdcKbps(0);
782 
783  for (UtReqInfoContainer_t::iterator it = m_utRequestInfos.begin(); it != m_utRequestInfos.end();
784  it++)
785  {
786  // estimation of the C/N0 is done when scheduling UT
787  Ptr<SatDamaEntry> damaEntry = m_utInfos.at(it->first)->GetDamaEntry();
788 
789  // process received CRs
790  m_utInfos.at(it->first)->UpdateDamaEntryFromCrs();
791 
792  // update allocation request information to be used later to request capacity from frame
793  // allocator
794  it->second.m_cno = m_utInfos.at(it->first)->GetCnoEstimation();
795 
796  // set control slot generation on or off
797  it->second.m_generateCtrlSlot = m_utInfos.at(it->first)->IsControlSlotGenerationTime();
798 
799  for (uint8_t i = 0; i < damaEntry->GetRcCount(); i++)
800  {
801  double superFrameDurationInSeconds =
803  ->GetDuration()
804  .GetSeconds();
805 
806  it->second.m_reqPerRc[i].m_craBytes =
807  (SatConstVariables::BITS_IN_KBIT * damaEntry->GetCraInKbps(i) *
808  superFrameDurationInSeconds) /
810  it->second.m_reqPerRc[i].m_rbdcBytes =
811  (SatConstVariables::BITS_IN_KBIT * damaEntry->GetRbdcInKbps(i) *
812  superFrameDurationInSeconds) /
814  it->second.m_reqPerRc[i].m_vbdcBytes = damaEntry->GetVbdcInBytes(i);
815 
816  // Collect the requested rate for all UTs per beam
817  requestedCraRbdcKbps += damaEntry->GetCraInKbps(i);
818  requestedCraRbdcKbps += damaEntry->GetRbdcInKbps(i);
819 
820  uint16_t minRbdcCraDeltaRateInKbps =
821  std::max(0, damaEntry->GetMinRbdcInKbps(i) - damaEntry->GetCraInKbps(i));
822  it->second.m_reqPerRc[i].m_minRbdcBytes =
823  (SatConstVariables::BITS_IN_KBIT * minRbdcCraDeltaRateInKbps *
824  superFrameDurationInSeconds) /
826 
827  // if UT is not requesting any RBDC for this RC then set minimum RBDC 0
828  // This means that no RBDC is actively requested for this RC
829  if (it->second.m_reqPerRc[i].m_rbdcBytes == 0)
830  {
831  it->second.m_reqPerRc[i].m_minRbdcBytes = 0;
832  }
833 
834  NS_ASSERT(
835  (it->second.m_reqPerRc[i].m_minRbdcBytes <= it->second.m_reqPerRc[i].m_rbdcBytes));
836 
837  // it->second.m_reqPerRc[i].m_rbdcBytes =
838  // std::max(it->second.m_reqPerRc[i].m_minRbdcBytes,
839  // it->second.m_reqPerRc[i].m_rbdcBytes);
840 
841  // write backlog requests traces starts ...
842  std::stringstream head;
843  head << Now().GetSeconds() << ", ";
844  head << m_beamId << ", ";
845  head << Singleton<SatIdMapper>::Get()->GetUtIdWithMac(it->first) << ", ";
846 
847  std::stringstream rbdcTail;
848  rbdcTail << SatEnums::DA_RBDC << ", ";
849  rbdcTail << damaEntry->GetRbdcInKbps(i);
850 
851  m_backlogRequestsTrace(head.str() + rbdcTail.str());
852 
853  std::stringstream vbdcTail;
854  vbdcTail << SatEnums::DA_VBDC << ", ";
855  vbdcTail << damaEntry->GetVbdcInBytes(i);
856 
857  m_backlogRequestsTrace(head.str() + vbdcTail.str());
858  // ... write backlog requests traces ends
859  }
860  }
861 
862  return requestedCraRbdcKbps;
863 }
864 
865 void
867 {
868  NS_LOG_FUNCTION(this);
869 
870  if (m_utInfos.size() > 0)
871  {
872  // sort UT requests according to C/N0 of the UTs
874 
876 
877  for (UtReqInfoContainer_t::iterator it = m_utRequestInfos.begin();
878  it != m_utRequestInfos.end();
879  it++)
880  {
881  allocReqs.push_back(&(it->second));
882  }
883 
884  // request capacity for UTs from frame allocator
885  m_superframeAllocator->PreAllocateSymbols(allocReqs);
886  }
887 }
888 
889 uint32_t
892 {
893  NS_LOG_FUNCTION(this);
894 
895  uint32_t offeredCraRbdcKbps(0);
896 
897  for (UtReqInfoContainer_t::iterator it = m_utRequestInfos.begin(); it != m_utRequestInfos.end();
898  it++)
899  {
900  Ptr<SatDamaEntry> damaEntry = m_utInfos.at(it->first)->GetDamaEntry();
901  SatFrameAllocator::UtAllocInfoContainer_t::const_iterator allocInfo =
902  utAllocContainer.find(it->first);
903 
904  if (allocInfo != utAllocContainer.end())
905  {
906  // update time to send next control slot, if control slot is allocated
907  if (allocInfo->second.second)
908  {
909  m_utInfos.at(allocInfo->first)->SetControlSlotGenerationTime(m_controlSlotInterval);
910  }
911 
912  double superFrameDurationInSeconds =
914  ->GetDuration()
915  .GetSeconds();
916 
917  for (uint32_t i = 0; i < allocInfo->second.first.size(); i++)
918  {
919  uint32_t rateBasedBytes =
920  (SatConstVariables::BITS_IN_KBIT * damaEntry->GetCraInKbps(i) *
921  superFrameDurationInSeconds) /
923  rateBasedBytes += (SatConstVariables::BITS_IN_KBIT * damaEntry->GetRbdcInKbps(i) *
924  superFrameDurationInSeconds) /
926 
927  offeredCraRbdcKbps += (uint32_t)((allocInfo->second.first[i] *
929  superFrameDurationInSeconds /
931  0.5);
932 
933  NS_LOG_INFO("UT: " << allocInfo->first << " RC index: " << i
934  << " rate based bytes: " << rateBasedBytes
935  << " allocated bytes: " << allocInfo->second.first[i]);
936 
937  // The scheduler has allocated more than the rate based bytes (CRA+RBDC)
938  if (rateBasedBytes < allocInfo->second.first[i])
939  {
940  // Requested VBDC
941  uint32_t vbdcBytes = damaEntry->GetVbdcInBytes(i);
942 
943  NS_LOG_INFO("UT: " << allocInfo->first << " RC index: " << i
944  << " requested VBDC bytes: " << vbdcBytes);
945 
946  // Allocated VBDC for this RC index
947  uint32_t allocVbdcBytes = allocInfo->second.first[i] - rateBasedBytes;
948 
949  // Allocated less than requested
950  if (vbdcBytes > allocVbdcBytes)
951  {
952  uint32_t remainingVbdcBytes = vbdcBytes - allocVbdcBytes;
953 
954  NS_LOG_INFO("UT: " << allocInfo->first << " RC index: " << i
955  << " VBDC allocation: " << allocVbdcBytes
956  << " remaining VBDC bytes: " << remainingVbdcBytes);
957 
958  damaEntry->SetVbdcInBytes(i, remainingVbdcBytes);
959  }
960  // Allocated more or equal to requested bytes
961  else
962  {
963  NS_LOG_INFO("UT: " << allocInfo->first << " RC index: " << i
964  << " VBDC allocation: " << allocVbdcBytes
965  << " remaining VBDC bytes: " << 0);
966 
967  damaEntry->SetVbdcInBytes(i, 0);
968  }
969  }
970  }
971  }
972  // decrease persistence values
973  damaEntry->DecrementDynamicRatePersistence();
974  damaEntry->DecrementVolumeBacklogPersistence();
975  }
976  return offeredCraRbdcKbps;
977 }
978 
979 void
980 SatBeamScheduler::TransferUtToBeam(Address utId, Ptr<SatBeamScheduler> destination)
981 {
982  NS_LOG_FUNCTION(this << utId << destination->m_satId << destination->m_beamId);
983 
984  UtInfoMap_t::iterator utIterator = m_utInfos.find(utId);
985  if (utIterator == m_utInfos.end())
986  {
987  // Check if handover already happened
988  NS_ASSERT_MSG(destination->HasUt(utId), "UT is not part of the source beam");
989  }
990  else
991  {
992  // Moving UT infos between beams
993  Ptr<SatUtInfo> utInfo = utIterator->second;
994  destination->AddUtInfo(utId, utInfo);
995  RemoveUtInfo(utIterator);
996 
997  // Handling capacity requests left and C/No estimations
998  switch (m_handoverStrategy)
999  {
1000  case BASIC: {
1001  utInfo->ClearCrMsgs();
1002  break;
1003  }
1004  case CHECK_GATEWAY: {
1005  if (m_satAddress != destination->m_satAddress ||
1006  m_gwAddress != destination->m_gwAddress)
1007  {
1008  utInfo->ClearCrMsgs();
1009  }
1010  break;
1011  }
1012  default:
1013  NS_FATAL_ERROR("Unknown handover strategy");
1014  }
1015  }
1016 }
1017 
1018 void
1019 SatBeamScheduler::ConnectUt(Mac48Address address)
1020 {
1021  NS_LOG_FUNCTION(this << address);
1022 
1023  m_orbiterNetDevice->ConnectUt(address, m_beamId);
1024  m_gwMac->ConnectUt(address);
1025 }
1026 
1027 void
1028 SatBeamScheduler::DisconnectUt(Mac48Address address)
1029 {
1030  NS_LOG_FUNCTION(this << address);
1031 
1032  m_orbiterNetDevice->DisconnectUt(address, m_beamId);
1033  m_gwMac->DisconnectUt(address);
1034 }
1035 
1036 void
1037 SatBeamScheduler::ConnectGw(Mac48Address address)
1038 {
1039  NS_LOG_FUNCTION(this << address);
1040 
1041  m_orbiterNetDevice->ConnectGw(address, m_beamId);
1042 }
1043 
1044 void
1045 SatBeamScheduler::DisconnectGw(Mac48Address address)
1046 {
1047  NS_LOG_FUNCTION(this << address);
1048 
1049  m_orbiterNetDevice->DisconnectGw(address, m_beamId);
1050 }
1051 
1052 void
1054 {
1055  NS_LOG_FUNCTION(this << utId);
1056 
1057  UtInfoMap_t::iterator utIterator = m_utInfos.find(utId);
1058  if (utIterator == m_utInfos.end())
1059  {
1060  NS_FATAL_ERROR("Trying to remove a UT not connected to a beam: " << utId);
1061  }
1062 
1063  // Moving UT infos between beams
1064  Ptr<SatUtInfo> utInfo = utIterator->second;
1065  RemoveUtInfo(utIterator);
1066 }
1067 
1068 Ptr<SatTimuMessage>
1070 {
1071  NS_LOG_FUNCTION(this);
1072 
1073  Ptr<SatTimuMessage> timuMsg = CreateObject<SatTimuMessage>();
1074  timuMsg->SetAllocatedSatId(m_satId);
1075  timuMsg->SetAllocatedBeamId(m_beamId);
1076  timuMsg->SetSatAddress(m_satAddress);
1077  timuMsg->SetGwAddress(m_gwAddress);
1078  return timuMsg;
1079 }
1080 
1081 void
1083 {
1084  NS_LOG_FUNCTION(this << logonChannelId);
1085 
1086  DoubleValue maxId;
1087  m_raChRandomIndex->GetAttribute("Max", maxId);
1088  uint32_t maxIndex = maxId.Get();
1089 
1090  if (logonChannelId > maxIndex)
1091  {
1092  NS_FATAL_ERROR("Cannot use channel ID " << logonChannelId
1093  << " for logon as it doesn't exist");
1094  }
1095 
1096  if (maxIndex != 0)
1097  {
1098  // Allows to still return the channel 0 as the random access
1099  // channel for UTs without entering in an infinite loop in AddUt
1100  m_logonChannelIndex = logonChannelId;
1101  }
1102 }
1103 
1104 void
1106 {
1107  NS_LOG_FUNCTION(this << useLora);
1108 
1109  m_useLora = useLora;
1110 }
1111 
1112 } // 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.
void DisconnectGw(Mac48Address address)
Disconnect a new GW address from this scheduler.
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.
void DisconnectUt(Mac48Address address)
Disconnect a new UT address from this scheduler.
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 ConnectUt(Mac48Address address)
Connect a new UT address to this scheduler.
void ConnectGw(Mac48Address address)
Connect a new GW address to this scheduler.
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.
void Initialize(uint32_t satId, uint32_t beamId, Ptr< SatNetDevice > gwNetDevice, Ptr< SatOrbiterNetDevice > orbiterNetDevice, SatBeamScheduler::SendCtrlMsgCallback cb, Ptr< SatSuperframeSeq > seq, uint32_t maxFrameSizeInBytes, Address satAddress, Address gwAddress)
TracedCallback< uint32_t, uint32_t > m_frameUtLoadTrace
Trace count of UTs scheduled per Frame.
bool HasUt()
Check whether an UT is handled by this scheduler.
Ptr< SatOrbiterNetDevice > m_orbiterNetDevice
OrbiterNetDevice on satellite linked to this beam.
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).
uint32_t m_satId
ID of the satellite using this beam.
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.
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.
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.
void SetUseLora(bool useLora)
Set if SNS-3 is used with Lora standard.
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.
bool m_useLora
Flag indicating if lora standard is used.
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.
Ptr< SatGwMac > m_gwMac
GW MAC linked to this beam.
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.