Loading...
Searching...
No Matches
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
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
52NS_LOG_COMPONENT_DEFINE("SatBeamScheduler");
53
54namespace ns3
55{
56
57// UtInfo class declarations for SatBeamScheduler
58SatBeamScheduler::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
71Ptr<SatDamaEntry>
73{
74 NS_LOG_FUNCTION(this);
75
76 return m_damaEntry;
77}
78
79void
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
132double
134{
135 NS_LOG_FUNCTION(this);
136
137 return m_cnoEstimator->GetCnoEstimation();
138}
139
140void
142{
143 NS_LOG_FUNCTION(this << sample);
144
145 m_cnoEstimator->AddSample(sample);
146}
147
148void
150{
151 NS_LOG_FUNCTION(this << crMsg);
152
153 m_crContainer.push_back(crMsg);
154}
155
156void
158{
159 NS_LOG_FUNCTION(this);
160
161 m_crContainer.clear();
162}
163
164bool
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
179void
181{
182 NS_LOG_FUNCTION(this);
183
184 m_controlSlotGenerationTime = Simulator::Now() + offset;
185}
186
187// SatBeamScheduler
188
189NS_OBJECT_ENSURE_REGISTERED(SatBeamScheduler);
190
191TypeId
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)),
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)),
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),
287 m_txCallback(),
292 m_superframeAllocatorType(SatEnums::DEFAULT_SUPERFRAME_ALLOCATOR),
294{
295 NS_LOG_FUNCTION(this);
296}
297
299{
300 NS_LOG_FUNCTION(this);
301}
302
303void
305{
306 NS_LOG_FUNCTION(this);
307 m_txCallback.Nullify();
308 Object::DoDispose();
309}
310
311bool
312SatBeamScheduler::Send(Ptr<SatControlMessage> msg)
313{
314 NS_LOG_FUNCTION(this << msg);
315
316 m_txCallback(msg, Mac48Address::GetBroadcast());
317 return true;
318}
319
320bool
321SatBeamScheduler::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
334bool
335SatBeamScheduler::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
343void
345{
346 NS_LOG_FUNCTION(this << &cb);
347
348 m_txTbtpCallback = cb;
349}
350
351void
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
446uint32_t
447SatBeamScheduler::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(
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
483void
484SatBeamScheduler::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
514void
515SatBeamScheduler::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
537bool
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
546bool
548{
549 NS_LOG_FUNCTION(this);
550
551 return !m_utInfos.empty();
552}
553
554void
555SatBeamScheduler::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
565void
566SatBeamScheduler::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
576void
577SatBeamScheduler::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
587Ptr<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
610void
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
626void
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
714void
715SatBeamScheduler::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
776uint32_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
865void
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
889uint32_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
979void
980SatBeamScheduler::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
1018void
1019SatBeamScheduler::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
1027void
1029{
1030 NS_LOG_FUNCTION(this << address);
1031
1032 m_orbiterNetDevice->DisconnectUt(address, m_beamId);
1033 m_gwMac->DisconnectUt(address);
1034}
1035
1036void
1037SatBeamScheduler::ConnectGw(Mac48Address address)
1038{
1039 NS_LOG_FUNCTION(this << address);
1040
1041 m_orbiterNetDevice->ConnectGw(address, m_beamId);
1042}
1043
1044void
1046{
1047 NS_LOG_FUNCTION(this << address);
1048
1049 m_orbiterNetDevice->DisconnectGw(address, m_beamId);
1050}
1051
1052void
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
1068Ptr<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
1081void
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
1104void
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.
Ptr< SatDamaEntry > m_damaEntry
DamaEntry of this UT info.
SatUtInfo(Ptr< SatDamaEntry > damaEntry, Ptr< SatCnoEstimator > cnoEstimator, Time controlSlotOffset, bool controlSlotsEnabled)
Construct SatUtInfo.
Ptr< SatCnoEstimator > m_cnoEstimator
Estimator for the C/N0.
void SetControlSlotGenerationTime(Time offset)
Set time for next time slot generation for this UT.
CrMsgContainer_t m_crContainer
Received CRs since last update round (call of the method UpdateDamaEntryFromCrs).
Time m_controlSlotGenerationTime
Time to send next control time slot.
bool m_controlSlotsEnabled
Flag to indicated if control time slots generation is enabled.
void AddCnoSample(double sample)
Add C/N0 sample to UT info's estimator.
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 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.
void AddRaChannels(std::vector< Ptr< SatTbtpMessage > > &tbtpContainer)
Add RA channel information to TBTP(s).
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.