satellite-ut-mac.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.fr>
21  */
22 
23 #include "satellite-ut-mac.h"
24 
30 #include "satellite-frame-conf.h"
31 #include "satellite-id-mapper.h"
32 #include "satellite-log.h"
33 #include "satellite-node-info.h"
37 #include "satellite-topology.h"
38 #include "satellite-utils.h"
40 
41 #include <ns3/boolean.h>
42 #include <ns3/log.h>
43 #include <ns3/mac48-address.h>
44 #include <ns3/packet.h>
45 #include <ns3/pointer.h>
46 #include <ns3/random-variable-stream.h>
47 #include <ns3/simulator.h>
48 #include <ns3/singleton.h>
49 
50 #include <iostream>
51 #include <map>
52 #include <set>
53 #include <sstream>
54 #include <utility>
55 #include <vector>
56 
57 NS_LOG_COMPONENT_DEFINE("SatUtMac");
58 
59 namespace ns3
60 {
61 
62 NS_OBJECT_ENSURE_REGISTERED(SatUtMac);
63 
64 TypeId
66 {
67  static TypeId tid =
68  TypeId("ns3::SatUtMac")
69  .SetParent<SatMac>()
70  .AddConstructor<SatUtMac>()
71  .AddAttribute("MaxHandoverMessages",
72  "Max amount of handover messages to send without a handover response "
73  "before loging off",
74  UintegerValue(20),
75  MakeUintegerAccessor(&SatUtMac::m_maxHandoverMessagesSent),
76  MakeUintegerChecker<uint32_t>())
77  .AddAttribute("SuperframeSequence",
78  "Superframe sequence containing information of superframes.",
79  PointerValue(),
80  MakePointerAccessor(&SatUtMac::m_superframeSeq),
81  MakePointerChecker<SatSuperframeSeq>())
82  .AddAttribute("GuardTime",
83  "Guard time in return link",
84  TimeValue(MicroSeconds(1)),
85  MakeTimeAccessor(&SatUtMac::m_guardTime),
86  MakeTimeChecker())
87  .AddAttribute("Scheduler",
88  "UT scheduler used by this Sat UT MAC.",
89  PointerValue(),
90  MakePointerAccessor(&SatUtMac::m_utScheduler),
91  MakePointerChecker<SatUtScheduler>())
92  .AddAttribute("WindowInitLogon",
93  "The initial window for logon waiting time before transmission.",
94  TimeValue(Seconds(20)),
95  MakeTimeAccessor(&SatUtMac::m_windowInitLogon),
96  MakeTimeChecker())
97  .AddAttribute("MaxWaitingTimeLogonResponse",
98  "Timeout for waiting for a response for a logon message.",
99  TimeValue(Seconds(1)),
100  MakeTimeAccessor(&SatUtMac::m_maxWaitingTimeLogonResponse),
101  MakeTimeChecker())
102  .AddAttribute("ClockDrift",
103  "Clock drift (number of ticks per second).",
104  IntegerValue(0),
105  MakeIntegerAccessor(&SatUtMac::m_clockDrift),
106  MakeIntegerChecker<int32_t>())
107  .AddTraceSource("DaResourcesTrace",
108  "Assigned dedicated access resources in return link to this UT.",
109  MakeTraceSourceAccessor(&SatUtMac::m_tbtpResourcesTrace),
110  "ns3::SatUtMac::TbtpResourcesTraceCallback");
111  return tid;
112 }
113 
114 TypeId
116 {
117  NS_LOG_FUNCTION(this);
118 
119  return GetTypeId();
120 }
121 
123  : SatMac(),
124  m_satId(0),
125  m_beamId(),
126  m_superframeSeq(),
127  m_timingAdvanceCb(),
128  m_randomAccess(nullptr),
129  m_guardTime(MicroSeconds(1)),
130  m_raChannel(0),
131  m_logonChannel(0),
132  m_loggedOn(true),
133  m_useLogon(false),
134  m_sendLogonTries(0),
135  m_windowInitLogon(Seconds(20)),
136  m_maxWaitingTimeLogonResponse(Seconds(1)),
137  m_waitingTimeLogonRng(CreateObject<UniformRandomVariable>()),
138  m_nextLogonTransmissionPossible(Seconds(0)),
139  m_crdsaUniquePacketId(1),
140  m_crdsaOnlyForControl(false),
141  m_nextPacketTime(Now()),
142  m_isRandomAccessScheduled(false),
143  m_timuInfo(0),
144  m_rcstState(SatUtMacState()),
145  m_lastNcrDateReceived(Seconds(0)),
146  m_ncr(0),
147  m_deltaNcr(0),
148  m_clockDrift(0),
149  m_handoverState(NO_HANDOVER),
150  m_handoverMessagesCount(0),
151  m_maxHandoverMessagesSent(20),
152  m_firstTransmittableSuperframeId(0),
153  m_handoverCallback(),
154  m_gatewayUpdateCallback(),
155  m_txCheckCallback(),
156  m_sliceSubscriptionCallback(),
157  m_sendLogonCallback(),
158  m_updateGwAddressCallback()
159 {
160  NS_LOG_FUNCTION(this);
161 
162  // default constructor should not be used
163  NS_FATAL_ERROR("SatUtMac::SatUtMac - Constructor not in use");
164 }
165 
166 SatUtMac::SatUtMac(Ptr<Node> node,
167  uint32_t satId,
168  uint32_t beamId,
169  Ptr<SatSuperframeSeq> seq,
170  bool crdsaOnlyForControl)
171  : SatMac(satId, beamId),
172  m_node(node),
173  m_satId(satId),
174  m_beamId(beamId),
175  m_superframeSeq(seq),
176  m_timingAdvanceCb(),
177  m_guardTime(MicroSeconds(1)),
178  m_raChannel(0),
179  m_logonChannel(0),
180  m_loggedOn(true),
181  m_useLogon(false),
182  m_sendLogonTries(0),
183  m_windowInitLogon(Seconds(20)),
184  m_maxWaitingTimeLogonResponse(Seconds(1)),
185  m_waitingTimeLogonRng(CreateObject<UniformRandomVariable>()),
186  m_nextLogonTransmissionPossible(Seconds(0)),
187  m_crdsaUniquePacketId(1),
188  m_crdsaOnlyForControl(crdsaOnlyForControl),
189  m_nextPacketTime(Now()),
190  m_isRandomAccessScheduled(false),
191  m_timuInfo(0),
192  m_rcstState(SatUtMacState()),
193  m_lastNcrDateReceived(Seconds(0)),
194  m_ncr(0),
195  m_deltaNcr(0),
196  m_clockDrift(0),
197  m_handoverState(NO_HANDOVER),
198  m_handoverMessagesCount(0),
199  m_maxHandoverMessagesSent(20),
200  m_firstTransmittableSuperframeId(0),
201  m_handoverCallback(),
202  m_gatewayUpdateCallback(),
203  m_txCheckCallback(),
204  m_sliceSubscriptionCallback(),
205  m_sendLogonCallback(),
206  m_updateGwAddressCallback()
207 {
208  NS_LOG_FUNCTION(this);
209 
210  m_uniformRandomVariable = CreateObject<UniformRandomVariable>();
211  m_tbtpContainer = CreateObject<SatTbtpContainer>(m_superframeSeq);
212 }
213 
215 {
216  NS_LOG_FUNCTION(this);
217 
218  m_randomAccess = nullptr;
219  m_tbtpContainer = nullptr;
220  m_timuInfo = nullptr;
221 }
222 
223 void
225 {
226  NS_LOG_FUNCTION(this);
227 
228  m_timingAdvanceCb.Nullify();
229  m_handoverCallback.Nullify();
230  m_gatewayUpdateCallback.Nullify();
231  m_txCheckCallback.Nullify();
232  m_sliceSubscriptionCallback.Nullify();
233  m_sendLogonCallback.Nullify();
234  m_updateGwAddressCallback.Nullify();
235  m_tbtpContainer->DoDispose();
236  m_utScheduler->DoDispose();
237  m_utScheduler = nullptr;
238 
240 }
241 
242 void
244 {
245  NS_LOG_FUNCTION(this << &cb);
246  m_handoverCallback = cb;
247 }
248 
249 void
251 {
252  NS_LOG_FUNCTION(this << &cb);
254 }
255 
256 void
258 {
259  NS_LOG_FUNCTION(this << &cb);
261 }
262 
263 void
265 {
266  NS_LOG_FUNCTION(this << &cb);
267 
268  m_txCheckCallback = cb;
269 }
270 
271 void
273 {
274  NS_LOG_FUNCTION(this << &cb);
275 
277 }
278 
279 void
281 {
282  NS_LOG_FUNCTION(this << &cb);
283 
284  m_sendLogonCallback = cb;
285 }
286 
287 void
289 {
290  NS_LOG_FUNCTION(this << &cb);
291 
293 }
294 
295 void
296 SatUtMac::SetSatelliteAddress(Address satelliteAddress)
297 {
298  m_satelliteAddress = satelliteAddress;
299  m_isRegenerative = true;
300 }
301 
302 Mac48Address
304 {
305  NS_LOG_FUNCTION(this);
306 
307  return m_gwAddress;
308 }
309 
310 void
311 SatUtMac::SetGwAddress(Mac48Address gwAddress)
312 {
313  NS_LOG_FUNCTION(this << gwAddress);
314 
315  m_gatewayUpdateCallback(gwAddress);
316  m_gwAddress = gwAddress;
317 }
318 
319 void
320 SatUtMac::SetNodeInfo(Ptr<SatNodeInfo> nodeInfo)
321 {
322  NS_LOG_FUNCTION(this << nodeInfo);
323 
324  m_tbtpContainer->SetMacAddress(nodeInfo->GetMacAddress());
325  m_utScheduler->SetNodeInfo(nodeInfo);
326  SatMac::SetNodeInfo(nodeInfo);
327 }
328 
329 void
331 {
332  NS_LOG_FUNCTION(this);
333  m_loggedOn = false;
336 }
337 
338 void
339 SatUtMac::SetLogonChannel(uint32_t channelId)
340 {
341  NS_LOG_FUNCTION(this);
342  m_logonChannel = channelId;
343  m_useLogon = true;
344 }
345 
346 void
347 SatUtMac::SetRaChannel(uint32_t raChannel)
348 {
349  NS_LOG_FUNCTION(this << raChannel);
350 
351  m_raChannel = raChannel;
352 }
353 
354 uint32_t
356 {
357  NS_LOG_FUNCTION(this);
358 
359  return m_raChannel;
360 }
361 
362 void
363 SatUtMac::SetRandomAccess(Ptr<SatRandomAccess> randomAccess)
364 {
365  NS_LOG_FUNCTION(this);
366 
367  m_randomAccess = randomAccess;
368  m_randomAccess->SetIsDamaAvailableCallback(
370 }
371 
372 bool
374 {
375  NS_LOG_FUNCTION(this);
376 
377  bool da = m_tbtpContainer->HasScheduledTimeSlots();
378  bool ra = (m_randomAccess != nullptr);
379  if (m_useLogon)
380  {
381  ra = ra && (m_raChannel != m_logonChannel);
382  }
383  return da || ra;
384 }
385 
386 bool
388 {
389  NS_LOG_FUNCTION(this);
390 
391  bool stateCorrect = (m_rcstState.GetState() == SatUtMacState::RcstState_t::READY_FOR_LOGON);
392  bool ncrReceived = !m_rcstState.IsNcrTimeout();
393 
394  return m_useLogon && stateCorrect && ncrReceived;
395 }
396 
397 void
399 {
400  NS_LOG_FUNCTION(this << &cb);
401 
402  m_timingAdvanceCb = cb;
403 
406 
407  if (Now() >= nextSuperFrameTxTime)
408  {
409  NS_FATAL_ERROR("Scheduling next superframe start time to the past!");
410  }
411 
412  Time schedulingDelay = nextSuperFrameTxTime - Now();
413 
414  Simulator::Schedule(GetRealSendingTime(schedulingDelay), &SatUtMac::DoFrameStart, this);
415 }
416 
417 void
419 {
420  NS_LOG_FUNCTION(this << &cb);
421 
423 }
424 
425 Time
426 SatUtMac::GetNextSuperFrameTxTime(uint8_t superFrameSeqId) const
427 {
428  NS_LOG_FUNCTION(this << (uint32_t)superFrameSeqId);
429 
430  Time timingAdvance = m_timingAdvanceCb();
431  Time txTime =
432  Singleton<SatRtnLinkTime>::Get()->GetNextSuperFrameTxTime(superFrameSeqId, timingAdvance);
433  return txTime;
434 }
435 
436 Time
437 SatUtMac::GetCurrentSuperFrameStartTime(uint8_t superFrameSeqId) const
438 {
439  NS_LOG_FUNCTION(this << (uint32_t)superFrameSeqId);
440 
441  Time timingAdvance = m_timingAdvanceCb();
442  Time txTime = Singleton<SatRtnLinkTime>::Get()->GetCurrentSuperFrameTxTime(superFrameSeqId,
443  timingAdvance);
444  return txTime;
445 }
446 
447 uint32_t
448 SatUtMac::GetCurrentSuperFrameId(uint8_t superFrameSeqId) const
449 {
450  NS_LOG_FUNCTION(this << (uint32_t)superFrameSeqId);
451 
452  return Singleton<SatRtnLinkTime>::Get()->GetCurrentSuperFrameCount(superFrameSeqId,
454 }
455 
456 void
457 SatUtMac::ScheduleTimeSlots(Ptr<SatTbtpMessage> tbtp)
458 {
459  NS_LOG_FUNCTION(this << tbtp);
460  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " received TBTP "
461  << tbtp->GetSuperframeCounter());
462 
473  ->GetConfigType() == SatSuperframeConf::CONFIG_TYPE_4)
474  {
475  return;
476  }
477 
478  Time timingAdvance = m_timingAdvanceCb();
479  Time txTime =
480  Singleton<SatRtnLinkTime>::Get()->GetSuperFrameTxTime(tbtp->GetSuperframeSeqId(),
481  tbtp->GetSuperframeCounter(),
482  timingAdvance);
483 
484  // The delay compared to Now when to start the transmission of this superframe
485  Time startDelay = txTime - Simulator::Now();
486 
487  // Add TBTP to a specific container
488  m_tbtpContainer->Add(txTime, tbtp);
489 
490  // if the calculated start time of the superframe is already in the past
491  if (txTime < Simulator::Now())
492  {
493  NS_FATAL_ERROR("UT: " << m_nodeInfo->GetMacAddress() << " received TBTP "
494  << tbtp->GetSuperframeCounter()
495  << ", which should have been sent already in the past");
496  }
497 
498  NS_LOG_INFO("Time to start sending the superframe for this UT: " << txTime.GetSeconds());
499  NS_LOG_INFO("Waiting delay before the superframe start: " << startDelay.GetSeconds());
500 
501  SatTbtpMessage::DaTimeSlotInfoItem_t info = tbtp->GetDaTimeslots(m_nodeInfo->GetMacAddress());
502 
503  // Counters for allocated TBTP resources
504  uint32_t payloadSumInSuperFrame = 0;
505  uint32_t payloadSumPerRcIndex[SatEnums::NUM_FIDS] = {};
506 
507  if (!info.second.empty())
508  {
509  NS_LOG_INFO("TBTP contains " << info.second.size()
510  << " timeslots for UT: " << m_nodeInfo->GetMacAddress());
511 
512  uint8_t frameId = info.first;
513 
514  // schedule time slots
515  for (SatTbtpMessage::DaTimeSlotConfContainer_t::iterator it = info.second.begin();
516  it != info.second.end();
517  it++)
518  {
519  Ptr<SatSuperframeConf> superframeConf =
521  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
522  Ptr<SatTimeSlotConf> timeSlotConf = *it;
523 
524  // Start time
525  Time slotDelay = startDelay + timeSlotConf->GetStartTime();
526  NS_LOG_INFO("Slot start delay: " << slotDelay.GetSeconds());
527 
528  // Duration
529  Ptr<SatWaveform> wf =
530  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
531  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
532 
533  bool drop = false;
534  if (timeSlotConf->GetSlotType() == SatTimeSlotConf::SLOT_TYPE_C)
535  {
536  wf = m_superframeSeq->GetWaveformConf()->GetWaveform(2);
537  duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
538  if (m_useLogon && m_rcstState.GetState() != SatUtMacState::RcstState_t::TDMA_SYNC &&
539  m_rcstState.GetState() != SatUtMacState::RcstState_t::READY_FOR_TDMA_SYNC)
540  {
541  drop = true;
542  }
543  }
544 
545  // Carrier
546  uint32_t carrierId =
547  m_superframeSeq->GetCarrierId(0, frameId, timeSlotConf->GetCarrierId());
548 
549  if (!drop)
550  {
551  // Schedule individual time slot
552  ScheduleDaTxOpportunity(slotDelay, duration, wf, timeSlotConf, carrierId);
553 
554  payloadSumInSuperFrame += wf->GetPayloadInBytes();
555  payloadSumPerRcIndex[timeSlotConf->GetRcIndex()] += wf->GetPayloadInBytes();
556  }
557  }
558  }
559 
560  // Assigned TBTP resources
561  m_tbtpResourcesTrace(payloadSumInSuperFrame);
562 
563  // Update the allocated TBTP resources for each RC index
564  for (uint32_t i = 0; i < SatEnums::NUM_FIDS; ++i)
565  {
566  m_assignedDaResourcesCallback(i, payloadSumPerRcIndex[i]);
567  }
568 }
569 
570 void
572  Time duration,
573  Ptr<SatWaveform> wf,
574  Ptr<SatTimeSlotConf> tsConf,
575  uint32_t carrierId)
576 {
577  NS_LOG_FUNCTION(this << transmitDelay.GetSeconds() << duration.GetSeconds()
578  << wf->GetPayloadInBytes() << (uint32_t)(tsConf->GetRcIndex())
579  << carrierId);
580  NS_LOG_INFO("After delay: " << transmitDelay.GetSeconds() << " duration: "
581  << duration.GetSeconds() << ", payload: " << wf->GetPayloadInBytes()
582  << ", rcIndex: " << (uint32_t)(tsConf->GetRcIndex())
583  << ", carrier: " << carrierId);
584 
585  transmitDelay = GetRealSendingTime(transmitDelay);
586 
587  if (transmitDelay >= Seconds(0))
588  {
589  Simulator::Schedule(transmitDelay,
591  this,
592  duration,
593  carrierId,
594  wf,
595  tsConf,
597  }
598 }
599 
600 void
601 SatUtMac::DoTransmit(Time duration,
602  uint32_t carrierId,
603  Ptr<SatWaveform> wf,
604  Ptr<SatTimeSlotConf> tsConf,
606 {
607  NS_LOG_FUNCTION(this << duration.GetSeconds() << wf->GetPayloadInBytes() << carrierId
608  << (uint32_t)(tsConf->GetRcIndex()));
609 
610  if (!m_txCheckCallback())
611  {
612  NS_LOG_INFO("Tx is unavailable");
614  return;
615  }
616 
617  if ((m_rcstState.GetState() != SatUtMacState::RcstState_t::TDMA_SYNC) &&
618  (tsConf->GetSlotType() != SatTimeSlotConf::SLOT_TYPE_C) && m_useLogon)
619  {
620  return;
621  }
622 
623  SatPhy::PacketContainer_t packets =
624  FetchPackets(wf->GetPayloadInBytes(), tsConf->GetSlotType(), tsConf->GetRcIndex(), policy);
625 
626  if (wf == m_superframeSeq->GetWaveformConf()->GetWaveform(2))
627  {
628  if (packets.size() == 0)
629  {
630  Ptr<Packet> p = Create<Packet>(wf->GetPayloadInBytes());
631 
632  // Mark the PDU with FULL_PDU tag
635  p->AddPacketTag(tag);
636 
637  // Add MAC tag to identify the packet in lower layers
638  SatMacTag mTag;
641  {
642  mTag.SetDestAddress(Mac48Address::ConvertFrom(m_satelliteAddress));
643  }
644  else
645  {
647  }
648  mTag.SetSourceAddress(m_nodeInfo->GetMacAddress());
649  p->AddPacketTag(mTag);
650 
651  // Add MAC tag to identify the packet in lower layers
652  SatAddressE2ETag addressE2ETag;
653  addressE2ETag.SetE2EDestAddress(m_gwAddress);
654  addressE2ETag.SetE2ESourceAddress(m_nodeInfo->GetMacAddress());
655  p->AddPacketTag(addressE2ETag);
656 
657  packets.push_back(p);
658  }
659  }
660 
661  NS_LOG_INFO("DA Tx opportunity for UT: "
662  << m_nodeInfo->GetMacAddress() << " duration: " << duration.GetSeconds()
663  << ", payload: " << wf->GetPayloadInBytes() << ", carrier: " << carrierId
664  << ", RC index: " << (uint32_t)(tsConf->GetRcIndex()));
665 
668  txInfo.modCod = wf->GetModCod();
669  txInfo.fecBlockSizeInBytes = wf->GetPayloadInBytes();
671  txInfo.waveformId = wf->GetWaveformId();
672 
673  if (txInfo.waveformId == 2 && tsConf->GetSlotType() != SatTimeSlotConf::SLOT_TYPE_C)
674  {
675  NS_FATAL_ERROR("WF02 should only be used for control bursts");
676  }
677 
678  TransmitPackets(packets, duration, carrierId, txInfo);
679 }
680 
681 void
683  Ptr<SatWaveform> waveform,
684  uint32_t carrierId,
685  uint8_t rcIndex,
687 {
688  NS_LOG_FUNCTION(this << duration.GetSeconds() << waveform->GetPayloadInBytes() << carrierId
689  << (uint32_t)(rcIndex));
690  NS_LOG_INFO("Tx opportunity for UT: "
691  << m_nodeInfo->GetMacAddress() << " duration: " << duration.GetSeconds()
692  << ", payload: " << waveform->GetPayloadInBytes() << ", carrier: " << carrierId
693  << ", RC index: " << (uint32_t)(rcIndex));
694 
696 
698  uint32_t payloadBytes = waveform->GetPayloadInBytes();
699 
701  payloadBytes -= m_randomAccess->GetSlottedAlohaSignalingOverheadInBytes();
702 
703  if (payloadBytes < 1)
704  {
705  NS_FATAL_ERROR(
706  "SatUtMac::DoSlottedAlohaTransmit - Not enough capacity in Slotted ALOHA payload");
707  }
708 
709  ExtractPacketsToSchedule(packets,
710  payloadBytes,
712  rcIndex,
713  policy,
714  true);
715 
716  if (!packets.empty())
717  {
718  NS_LOG_INFO("Number of packets sent in a slotted ALOHA slot: " << packets.size());
719 
720  for (SatPhy::PacketContainer_t::const_iterator it = packets.begin(); it != packets.end();
721  ++it)
722  {
723  // Add packet trace entry:
724  m_packetTrace(Simulator::Now(),
726  m_nodeInfo->GetNodeType(),
727  m_nodeInfo->GetNodeId(),
728  m_nodeInfo->GetMacAddress(),
732  }
733 
736  txInfo.modCod = waveform->GetModCod();
737  txInfo.fecBlockSizeInBytes = waveform->GetPayloadInBytes();
739  txInfo.waveformId = waveform->GetWaveformId();
740 
741  TransmitPackets(packets, duration, carrierId, txInfo);
742  }
743 }
744 
745 void
747  Ptr<SatWaveform> waveform,
748  uint32_t carrierId,
749  uint8_t rcIndex,
751 {
752  NS_LOG_FUNCTION(this << duration.GetSeconds() << waveform->GetPayloadInBytes() << carrierId
753  << (uint32_t)(rcIndex));
754  NS_LOG_INFO("SatUtMac::DoEssaTransmit - Tx opportunity for UT: "
755  << m_nodeInfo->GetMacAddress() << " at time: " << Simulator::Now().GetSeconds()
756  << " duration: " << duration.GetSeconds()
757  << ", payload: " << waveform->GetPayloadInBytes() << ", carrier: " << carrierId
758  << ", RC index: " << (uint32_t)(rcIndex));
759 
761  uint32_t payloadBytes = waveform->GetPayloadInBytes();
762 
765  m_utScheduler->DoScheduling(packets,
766  payloadBytes,
768  rcIndex,
769  policy);
770 
771  if (!packets.empty())
772  {
773  NS_LOG_INFO("Number of packets sent in a ESSA frame: " << packets.size());
774 
775  for (SatPhy::PacketContainer_t::const_iterator it = packets.begin(); it != packets.end();
776  ++it)
777  {
778  // Add packet trace entry:
779  m_packetTrace(Simulator::Now(),
781  m_nodeInfo->GetNodeType(),
782  m_nodeInfo->GetNodeId(),
783  m_nodeInfo->GetMacAddress(),
787  }
788 
792  txInfo.modCod = waveform->GetModCod();
793  txInfo.fecBlockSizeInBytes = waveform->GetPayloadInBytes();
795  txInfo.waveformId = waveform->GetWaveformId();
796  txInfo.crdsaUniquePacketId =
797  m_crdsaUniquePacketId; // reuse the crdsaUniquePacketId to identify ESSA frames
798 
799  TransmitPackets(packets, duration, carrierId, txInfo);
803  Now() + duration; // TODO: this doesn't take into account the guard bands !!
806  duration = GetRealSendingTime(duration);
807  if (duration >= Seconds(0))
808  {
809  Simulator::Schedule(duration,
811  this,
813  }
815  }
816  else
817  {
819  }
820 }
821 
823 SatUtMac::FetchPackets(uint32_t payloadBytes,
825  uint8_t rcIndex,
827 {
828  NS_LOG_FUNCTION(this << payloadBytes << (uint32_t)(rcIndex));
829 
836 
837  if (payloadBytes <= 0)
838  {
839  NS_FATAL_ERROR("SatUtMac::FetchPackets - unvalid slot payload: " << payloadBytes);
840  }
841 
842  ExtractPacketsToSchedule(packets, payloadBytes, type, rcIndex, policy, false);
843 
844  // A valid packet received
845  if (!packets.empty())
846  {
847  NS_LOG_INFO("Number of packets: " << packets.size());
848 
849  for (SatPhy::PacketContainer_t::const_iterator it = packets.begin(); it != packets.end();
850  ++it)
851  {
852  // Add packet trace entry:
853  m_packetTrace(Simulator::Now(),
855  m_nodeInfo->GetNodeType(),
856  m_nodeInfo->GetNodeId(),
857  m_nodeInfo->GetMacAddress(),
861  }
862  }
863 
864  NS_LOG_INFO("The Frame PDU holds " << packets.size() << " RLE PDUs");
865 
866  return packets;
867 }
868 
869 void
871  Time duration,
872  uint32_t carrierId,
874 {
875  NS_LOG_FUNCTION(this << packets.size() << duration.GetSeconds() << carrierId);
876 
877  if (m_rcstState.GetState() == SatUtMacState::RcstState_t::HOLD_STANDBY)
878  {
880  }
881 
882  if (m_rcstState.GetState() == SatUtMacState::RcstState_t::READY_FOR_TDMA_SYNC)
883  {
885  }
886 
887  // If there are packets to send
888  if (!packets.empty())
889  {
890  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << ", transmitting " << packets.size()
891  << " packets, duration: " << duration.GetSeconds()
892  << ", carrier: " << carrierId);
893 
894  // Decrease a guard time from time slot duration.
895  Time durationWithoutGuardPeriod(duration - m_guardTime);
896  NS_LOG_INFO("Duration: " << duration.GetSeconds() << " duration with guard period: "
897  << durationWithoutGuardPeriod.GetSeconds());
898  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " send packet");
899 
900  SendPacket(packets, carrierId, durationWithoutGuardPeriod, txInfo);
901  }
902 }
903 
904 void
906 {
907  NS_LOG_FUNCTION(this << event << (uint32_t)rcIndex);
908 
909  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " Queue: " << (uint32_t)rcIndex);
910 
911  // Check only the queue events from the control queue
912  if (rcIndex == SatEnums::CONTROL_FID)
913  {
914  if (event == SatQueue::FIRST_BUFFERED_PKT || event == SatQueue::BUFFERED_PKT)
915  {
916  NS_LOG_INFO("Buffered packet event received");
917 
918  if (m_randomAccess != nullptr)
919  {
920  NS_LOG_INFO("Doing Slotted ALOHA");
921 
923  }
924  }
925  }
926 }
927 
928 void
930 {
931  NS_LOG_FUNCTION(this << event << (uint32_t)rcIndex);
932 
933  NS_LOG_INFO("SatUtMac::ReceiveQueueEventEssa - UT: " << m_nodeInfo->GetMacAddress()
934  << " time: " << Now().GetSeconds()
935  << " Queue: " << (uint32_t)rcIndex);
936 
937  // DoRandomAccess only if it is not scheduled yet
938  // NOTE: could use m_nextPacketTime to do the check
940  {
941  if (event == SatQueue::FIRST_BUFFERED_PKT || event == SatQueue::BUFFERED_PKT)
942  {
943  NS_LOG_INFO("SatUtMac::ReceiveQueueEventEssa - Buffered packet event received");
944 
945  if (m_randomAccess != nullptr)
946  {
947  NS_LOG_INFO("SatUtMac::ReceiveQueueEventEssa - Doing ESSA");
948 
950  }
951  }
952  }
953 }
954 
955 void
956 SatUtMac::SendLogon(Ptr<Packet> packet)
957 {
959  packets.push_back(packet);
960 
961  Ptr<SatSuperframeConf> superframeConf =
963  uint8_t frameId = superframeConf->GetRaChannelFrameId(m_logonChannel);
964  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
965 
966  Ptr<SatTimeSlotConf> timeSlotConf = frameConf->GetTimeSlotConf(0);
967 
968  Ptr<SatWaveform> wf =
969  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
970  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
971 
972  uint32_t carrierId = m_superframeSeq->GetCarrierId(SatConstVariables::SUPERFRAME_SEQUENCE,
973  frameId,
974  timeSlotConf->GetCarrierId());
975 
978  txInfo.modCod = wf->GetModCod();
979  txInfo.sliceId = 0;
980  txInfo.fecBlockSizeInBytes = wf->GetPayloadInBytes();
982  txInfo.waveformId = wf->GetWaveformId();
983 
984  Time waitingTime = Seconds(m_waitingTimeLogonRng->GetValue(0.0,
985  pow(1 + m_sendLogonTries, 2) *
986  m_windowInitLogon.GetSeconds()));
988  waitingTime = GetRealSendingTime(waitingTime);
989  if (waitingTime >= Seconds(0))
990  {
991  Simulator::Schedule(waitingTime,
993  this,
994  packets,
995  duration,
996  carrierId,
997  txInfo);
998  }
999 
1001  Simulator::Now() + m_maxWaitingTimeLogonResponse + waitingTime;
1002 }
1003 
1004 void
1005 SatUtMac::Receive(SatPhy::PacketContainer_t packets, Ptr<SatSignalParameters> /*rxParams*/)
1006 {
1007  NS_LOG_FUNCTION(this << packets.size());
1008 
1009  // Add packet trace entry:
1010  m_packetTrace(Simulator::Now(),
1012  m_nodeInfo->GetNodeType(),
1013  m_nodeInfo->GetNodeId(),
1014  m_nodeInfo->GetMacAddress(),
1017  SatUtils::GetPacketInfo(packets));
1018 
1019  // Invoke the `Rx` and `RxDelay` trace sources.
1020  RxTraces(packets);
1021 
1022  m_receptionDates.push(Simulator::Now());
1023  if (m_receptionDates.size() > 3)
1024  {
1025  m_receptionDates.pop();
1026  }
1027 
1028  for (SatPhy::PacketContainer_t::iterator i = packets.begin(); i != packets.end(); i++)
1029  {
1030  // Remove packet tag
1031  SatMacTag macTag;
1032  bool mSuccess = (*i)->PeekPacketTag(macTag);
1033  if (!mSuccess)
1034  {
1035  NS_FATAL_ERROR("MAC tag was not found from the packet!");
1036  }
1037 
1038  SatAddressE2ETag addressE2ETag;
1039  mSuccess = (*i)->PeekPacketTag(addressE2ETag);
1040  if (!mSuccess)
1041  {
1042  NS_FATAL_ERROR("SatAddressE2ETag was not found from the packet!");
1043  }
1044 
1045  NS_LOG_INFO("Packet from " << macTag.GetSourceAddress() << " to "
1046  << macTag.GetDestAddress());
1047  NS_LOG_INFO("Receiver " << m_nodeInfo->GetMacAddress());
1048 
1049  Mac48Address destAddress = macTag.GetDestAddress();
1050  if (destAddress == m_nodeInfo->GetMacAddress() || destAddress.IsBroadcast() ||
1051  destAddress.IsGroup())
1052  {
1053  // Remove control msg tag
1054  SatControlMsgTag ctrlTag;
1055  bool cSuccess = (*i)->PeekPacketTag(ctrlTag);
1056 
1057  if (cSuccess)
1058  {
1060 
1062  {
1064  }
1065  else
1066  {
1067  NS_FATAL_ERROR("A control message received with not valid msg type!");
1068  }
1069  }
1070  else if (destAddress.IsBroadcast())
1071  {
1072  // TODO: dummy frames and other broadcast needed to handle
1073  // dummy frames should ignored already in Phy layer
1074  }
1075  // Control msg tag not found, send the packet to higher layer
1076  else
1077  {
1078  // Pass the receiver address to LLC
1079  m_rxCallback(*i,
1080  addressE2ETag.GetE2ESourceAddress(),
1081  addressE2ETag.GetE2EDestAddress());
1082  }
1083  }
1084  }
1085 }
1086 
1087 void
1089 {
1090  NS_LOG_FUNCTION(this);
1091 
1092  // Remove the mac tag
1093  SatMacTag macTag;
1094  packet->PeekPacketTag(macTag);
1095 
1096  SatAddressE2ETag addressE2ETag;
1097  packet->PeekPacketTag(addressE2ETag);
1098 
1099  // Peek control msg tag
1100  SatControlMsgTag ctrlTag;
1101  bool cSuccess = packet->PeekPacketTag(ctrlTag);
1102 
1103  if (!cSuccess)
1104  {
1105  NS_FATAL_ERROR("SatControlMsgTag not found in the packet!");
1106  }
1107 
1108  switch (ctrlTag.GetMsgType())
1109  {
1111  uint32_t tbtpId = ctrlTag.GetMsgId();
1112 
1113  Ptr<SatTbtpMessage> tbtp = DynamicCast<SatTbtpMessage>(m_readCtrlCallback(tbtpId));
1114 
1120  if (tbtp == nullptr)
1121  {
1122  NS_FATAL_ERROR("TBTP not found, check SatBeamHelper::CtrlMsgStoreTimeInFwdLink "
1123  "attribute is long enough!");
1124  }
1125 
1127  {
1129  m_firstTransmittableSuperframeId = tbtp->GetSuperframeCounter();
1130  }
1131  ScheduleTimeSlots(tbtp);
1132 
1133  packet->RemovePacketTag(macTag);
1134  packet->RemovePacketTag(addressE2ETag);
1135  packet->RemovePacketTag(ctrlTag);
1136 
1137  break;
1138  }
1140  // ARQ ACK messages are forwarded to LLC, since they may be fragmented
1141  m_rxCallback(packet, addressE2ETag.GetE2ESourceAddress(), macTag.GetDestAddress());
1142  break;
1143  }
1145  uint32_t raCtrlId = ctrlTag.GetMsgId();
1146  Ptr<SatRaMessage> raMsg = DynamicCast<SatRaMessage>(m_readCtrlCallback(raCtrlId));
1147 
1148  if (raMsg != nullptr)
1149  {
1150  uint32_t allocationChannelId = raMsg->GetAllocationChannelId();
1151  uint16_t backoffProbability = raMsg->GetBackoffProbability();
1152  uint16_t backoffTime = raMsg->GetBackoffTime();
1153 
1154  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress()
1155  << " Updating RA backoff probability for AC: "
1156  << allocationChannelId << " to: " << backoffProbability);
1157 
1158  m_randomAccess->SetBackoffProbability(allocationChannelId, backoffProbability);
1159  m_randomAccess->SetBackoffTime(allocationChannelId, backoffTime);
1160 
1161  packet->RemovePacketTag(macTag);
1162  packet->RemovePacketTag(addressE2ETag);
1163  packet->RemovePacketTag(ctrlTag);
1164  }
1165  else
1166  {
1172  std::stringstream msg;
1173  msg << "Control message " << ctrlTag.GetMsgType()
1174  << " is not found from the FWD link control msg container!";
1175  msg << " at: " << Now().GetSeconds() << "s";
1176  Singleton<SatLog>::Get()->AddToLog(SatLog::LOG_WARNING, "", msg.str());
1177  }
1178  break;
1179  }
1181  uint32_t timuCtrlId = ctrlTag.GetMsgId();
1182  Ptr<SatTimuMessage> timuMsg = DynamicCast<SatTimuMessage>(m_readCtrlCallback(timuCtrlId));
1183 
1184  if (timuMsg != nullptr)
1185  {
1186  uint32_t beamId = timuMsg->GetAllocatedBeamId();
1187  uint32_t satId = timuMsg->GetAllocatedSatId();
1188  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " switching from beam " << m_beamId
1189  << " to beam " << beamId);
1190  if (m_beamId != beamId)
1191  {
1192  NS_LOG_INFO("Storing TIM-U information internally for later");
1193  m_timuInfo = Create<SatTimuInfo>(beamId,
1194  satId,
1195  timuMsg->GetSatAddress(),
1196  timuMsg->GetGwAddress());
1197  }
1198  }
1199  else
1200  {
1206  std::stringstream msg;
1207  msg << "Control message " << ctrlTag.GetMsgType()
1208  << " is not found from the FWD link control msg container!";
1209  msg << " at: " << Now().GetSeconds() << "s";
1210  Singleton<SatLog>::Get()->AddToLog(SatLog::LOG_WARNING, "", msg.str());
1211  }
1212  break;
1213  }
1215  uint32_t sliceCtrlId = ctrlTag.GetMsgId();
1216  Ptr<SatSliceSubscriptionMessage> sliceMsg =
1217  DynamicCast<SatSliceSubscriptionMessage>(m_readCtrlCallback(sliceCtrlId));
1218 
1219  if (sliceMsg != nullptr)
1220  {
1221  if (m_nodeInfo->GetMacAddress() == sliceMsg->GetAddress())
1222  {
1223  m_sliceSubscriptionCallback(sliceMsg->GetSliceId());
1224  }
1225  }
1226  else
1227  {
1233  std::stringstream msg;
1234  msg << "Control message " << ctrlTag.GetMsgType()
1235  << " is not found from the FWD link control msg container!";
1236  msg << " at: " << Now().GetSeconds() << "s";
1237  Singleton<SatLog>::Get()->AddToLog(SatLog::LOG_WARNING, "", msg.str());
1238  }
1239  break;
1240  }
1242  uint32_t logonId = ctrlTag.GetMsgId();
1243  Ptr<SatLogonResponseMessage> logonMsg =
1244  DynamicCast<SatLogonResponseMessage>(m_readCtrlCallback(logonId));
1245 
1246  if (logonMsg != nullptr)
1247  {
1248  m_raChannel = logonMsg->GetRaChannel();
1249  m_loggedOn = true;
1250  m_sendLogonTries = 0;
1251  m_rcstState.SetLogOffCallback(MakeCallback(&SatUtMac::LogOff, this));
1253  m_deltaNcr = Simulator::Now().GetMicroSeconds() * m_clockDrift / 1000000.0;
1254  }
1255  else
1256  {
1262  std::stringstream msg;
1263  msg << "Control message " << ctrlTag.GetMsgType()
1264  << " is not found from the FWD link control msg container!";
1265  msg << " at: " << Now().GetSeconds() << "s";
1266  Singleton<SatLog>::Get()->AddToLog(SatLog::LOG_WARNING, "", msg.str());
1267  }
1268  break;
1269  }
1271  uint32_t ncrCtrlId = ctrlTag.GetMsgId();
1272  Ptr<SatNcrMessage> ncrMsg = DynamicCast<SatNcrMessage>(m_readCtrlCallback(ncrCtrlId));
1273 
1274  m_lastNcrDateReceived = m_ncrV2 ? m_receptionDates.front() : Simulator::Now();
1275  m_ncr = ncrMsg->GetNcrDate();
1277 
1278  if (m_rcstState.GetState() == SatUtMacState::RcstState_t::NCR_RECOVERY)
1279  {
1281  {
1283  }
1284  else
1285  {
1287  }
1288  }
1289  break;
1290  }
1292  uint32_t cmtCtrlId = ctrlTag.GetMsgId();
1293  Ptr<SatCmtMessage> cmtMsg = DynamicCast<SatCmtMessage>(m_readCtrlCallback(cmtCtrlId));
1294  int16_t burstTimeCorrection = cmtMsg->GetBurstTimeCorrection();
1295  m_deltaNcr -= burstTimeCorrection;
1296  break;
1297  }
1299  uint32_t logoffCtrlId = ctrlTag.GetMsgId();
1300  Ptr<SatLogoffMessage> logoffMsg =
1301  DynamicCast<SatLogoffMessage>(m_readCtrlCallback(logoffCtrlId));
1302  LogOff();
1303  break;
1304  }
1305  default: {
1306  NS_FATAL_ERROR("SatUtMac received a non-supported control packet!");
1307  break;
1308  }
1309  }
1310 }
1311 
1312 void
1314 {
1315  NS_LOG_FUNCTION(this << randomAccessTriggerType);
1316 
1317  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress());
1318 
1319  if ((m_rcstState.GetState() != SatUtMacState::RcstState_t::TDMA_SYNC) && m_useLogon)
1320  {
1321  return;
1322  }
1323 
1326  m_isRandomAccessScheduled = false;
1327 
1329 
1331  uint32_t allocationChannel = GetNextRandomAccessAllocationChannel();
1332 
1333  if (m_useLogon && allocationChannel == m_logonChannel)
1334  {
1335  NS_LOG_INFO("Logon channel cannot be used for RA transmition");
1336  return;
1337  }
1338 
1340  txOpportunities = m_randomAccess->DoRandomAccess(allocationChannel, randomAccessTriggerType);
1341 
1344  {
1345  Time txOpportunity = GetRealSendingTime(
1346  Time::FromInteger(txOpportunities.slottedAlohaTxOpportunity, Time::MS));
1347 
1348  NS_LOG_INFO("Processing Slotted ALOHA results, Tx evaluation @: "
1349  << (Now() + txOpportunity).GetSeconds() << " seconds");
1350 
1352  if (txOpportunity >= Seconds(0))
1353  {
1354  Simulator::Schedule(txOpportunity,
1356  this,
1357  allocationChannel);
1358  }
1359  }
1361  else if (txOpportunities.txOpportunityType == SatEnums::RA_TX_OPPORTUNITY_CRDSA)
1362  {
1363  NS_LOG_INFO("Processing CRDSA results");
1364 
1366  ScheduleCrdsaTransmission(allocationChannel, txOpportunities);
1367  }
1369  else if (txOpportunities.txOpportunityType == SatEnums::RA_TX_OPPORTUNITY_ESSA)
1370  {
1371  NS_LOG_INFO("SatUtMac::DoRandomAccess - Processing ESSA results");
1376  Time txOpportunity = GetRealSendingTime(
1377  Time::FromInteger(txOpportunities.slottedAlohaTxOpportunity, Time::MS));
1378 
1380  if (txOpportunity >= Seconds(0))
1381  {
1382  Simulator::Schedule(txOpportunity,
1384  this,
1385  allocationChannel);
1386  }
1387  }
1388 }
1389 
1390 uint32_t
1392 {
1393  NS_LOG_FUNCTION(this);
1394 
1395  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " has allocation channel " << m_raChannel);
1396 
1398  return m_raChannel;
1399 }
1400 
1401 void
1403 {
1404  NS_LOG_FUNCTION(this << allocationChannel);
1405 
1406  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " AC: " << allocationChannel);
1407 
1411  if (!m_tbtpContainer->HasScheduledTimeSlots())
1412  {
1413  NS_LOG_INFO("No known DAMA, selecting a slot for Slotted ALOHA");
1414 
1415  Ptr<SatSuperframeConf> superframeConf =
1417  uint8_t frameId = superframeConf->GetRaChannelFrameId(allocationChannel);
1418  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
1419  uint32_t timeSlotCount = frameConf->GetTimeSlotCount();
1420 
1421  std::pair<bool, uint32_t> result = std::make_pair(false, 0);
1422  Time superframeStartTime =
1424 
1425  if (Now() < superframeStartTime)
1426  {
1427  NS_FATAL_ERROR("SatUtMac::ScheduleSlottedAlohaTransmission - Invalid SF start time");
1428  }
1429 
1431 
1432  NS_LOG_INFO("Searching for next available slot");
1433 
1436  while (!result.first)
1437  {
1438  NS_LOG_INFO("SuperFrameId: " << superFrameId << ", superframeStartTime: "
1439  << superframeStartTime.GetSeconds());
1440 
1441  result = SearchFrameForAvailableSlot(superframeStartTime,
1442  frameConf,
1443  timeSlotCount,
1444  superFrameId,
1445  allocationChannel);
1446 
1447  if (!result.first)
1448  {
1449  NS_LOG_INFO("Increasing frame offset!");
1450  superFrameId++;
1451  superframeStartTime += frameConf->GetDuration();
1452  }
1453  }
1454 
1456  Ptr<SatTimeSlotConf> timeSlotConf = frameConf->GetTimeSlotConf(result.second);
1457 
1459  Time slotStartTime = superframeStartTime + timeSlotConf->GetStartTime();
1460  Time offset = slotStartTime - Now();
1461 
1462  if (offset.IsStrictlyNegative())
1463  {
1464  NS_FATAL_ERROR("SatUtMac::ScheduleSlottedAlohaTransmission - Invalid transmit time: "
1465  << offset.GetSeconds());
1466  }
1467 
1469  Ptr<SatWaveform> wf =
1470  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
1471  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
1472 
1474  uint32_t carrierId =
1475  m_superframeSeq->GetCarrierId(0, frameId, timeSlotConf->GetCarrierId());
1476 
1477  NS_LOG_INFO("Starting to schedule, SF ID: "
1478  << superFrameId << " slot: " << result.second
1479  << " SF start: " << superframeStartTime.GetSeconds()
1480  << " Tx start: " << (Now() + offset).GetSeconds()
1481  << " duration: " << duration.GetSeconds() << " carrier ID: " << carrierId
1482  << " payload in bytes: " << wf->GetPayloadInBytes());
1483 
1485  offset = GetRealSendingTime(offset);
1486  if (offset >= Seconds(0))
1487  {
1488  Simulator::Schedule(offset,
1490  this,
1491  duration,
1492  wf,
1493  carrierId,
1494  uint8_t(SatEnums::CONTROL_FID),
1496  }
1497  }
1498  else
1499  {
1500  NS_LOG_INFO("UT has known DAMA, aborting Slotted ALOHA");
1501  }
1502 }
1503 
1504 std::pair<bool, uint32_t>
1505 SatUtMac::SearchFrameForAvailableSlot(Time superframeStartTime,
1506  Ptr<SatFrameConf> frameConf,
1507  uint32_t timeSlotCount,
1508  uint32_t superFrameId,
1509  uint32_t allocationChannel)
1510 {
1511  NS_LOG_FUNCTION(this << superframeStartTime << timeSlotCount << superFrameId
1512  << allocationChannel);
1513 
1514  Time opportunityOffset = Now() - superframeStartTime;
1515 
1516  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress()
1517  << " offset: " << opportunityOffset.GetSeconds());
1518 
1521  if (opportunityOffset.IsStrictlyNegative())
1522  {
1523  opportunityOffset = Seconds(0);
1524  }
1525 
1526  return FindNextAvailableRandomAccessSlot(opportunityOffset,
1527  frameConf,
1528  timeSlotCount,
1529  superFrameId,
1530  allocationChannel);
1531 }
1532 
1533 std::pair<bool, uint32_t>
1535  Ptr<SatFrameConf> frameConf,
1536  uint32_t timeSlotCount,
1537  uint32_t superFrameId,
1538  uint32_t allocationChannel)
1539 {
1540  NS_LOG_FUNCTION(this << opportunityOffset << timeSlotCount << superFrameId
1541  << allocationChannel);
1542 
1543  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress());
1544 
1545  Ptr<SatTimeSlotConf> slotConf;
1546  uint32_t slotId;
1547  bool availableSlotFound = false;
1548 
1550  for (slotId = 0; slotId < timeSlotCount; slotId++)
1551  {
1552  slotConf = frameConf->GetTimeSlotConf(slotId);
1553 
1554  // NS_LOG_INFO ("Slot: " << slotId <<
1555  // " slot offset: " << slotConf->GetStartTime.GetSeconds () <<
1556  // " opportunity offset: " << opportunityOffset.GetSeconds ());
1557 
1560  if (slotConf->GetStartTime() >= opportunityOffset)
1561  {
1563  if (UpdateUsedRandomAccessSlots(superFrameId, allocationChannel, slotId))
1564  {
1565  availableSlotFound = true;
1566  break;
1567  }
1568  }
1569  }
1570 
1571  NS_LOG_INFO("Success: " << availableSlotFound << " SF: " << superFrameId << " AC: "
1572  << allocationChannel << " slot: " << slotId << "/" << timeSlotCount);
1573 
1574  return std::make_pair(availableSlotFound, slotId);
1575 }
1576 
1577 void
1578 SatUtMac::ScheduleEssaTransmission(uint32_t allocationChannel)
1579 {
1580  // TODO: do we really need the allocationChannel ???
1581  NS_LOG_FUNCTION(this << allocationChannel);
1582 
1583  NS_LOG_INFO("SatUtMac::ScheduleEssaTransmission - UT: " << m_nodeInfo->GetMacAddress()
1584  << " time: " << Now().GetSeconds()
1585  << " AC: " << allocationChannel);
1586 
1588  Time offset = m_nextPacketTime - Now();
1589 
1590  if (offset.IsStrictlyNegative())
1591  {
1593  offset = Seconds(0);
1594  }
1595 
1597  Ptr<SatSuperframeConf> superframeConf =
1599  uint8_t frameId = superframeConf->GetRaChannelFrameId(allocationChannel);
1600  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
1601  Ptr<SatTimeSlotConf> timeSlotConf = frameConf->GetTimeSlotConf(0); // only one timeslot on ESSA
1602 
1603  Ptr<SatWaveform> wf =
1604  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
1605  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
1606 
1607  NS_LOG_INFO("SatUtMac::ScheduleEssaTransmission - Starting to schedule @ "
1608  << Now().GetSeconds() << " Tx start: " << (Now() + offset).GetSeconds()
1609  << " duration: " << duration.GetSeconds()
1610  << " payload in bytes: " << wf->GetPayloadInBytes());
1611 
1613  uint32_t carrierId = 0; // TODO: for now we use 0 as we have a single carrier
1614 
1616  offset = GetRealSendingTime(offset);
1617  if (offset >= Seconds(0))
1618  {
1619  Simulator::Schedule(offset,
1621  this,
1622  duration,
1623  wf,
1624  carrierId,
1625  uint8_t(SatEnums::CONTROL_FID),
1627  }
1628 }
1629 
1630 void
1631 SatUtMac::ScheduleCrdsaTransmission(uint32_t allocationChannel,
1633 {
1634  NS_LOG_FUNCTION(this << allocationChannel);
1635 
1636  // get current superframe ID
1637  Time now = Simulator::Now();
1640  NS_LOG_INFO("Checking for CRDSA transmission at "
1641  << now.GetMilliSeconds() - superFrameStart.GetMilliSeconds()
1642  << " milliseconds into superframe " << superFrameId);
1643 
1644  // TODO: check we didn't already scheduled packets for this superframe
1645  // (because we are moving so fast, for instance, that we are now at the end of the
1646  // window for this "past" superframe instead of the beginning of the next one)
1647 
1648  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " AC: " << allocationChannel
1649  << ", SF: " << superFrameId << ", num of opportunities: "
1650  << txOpportunities.crdsaTxOpportunities.size());
1651 
1652  std::map<uint32_t, std::set<uint32_t>>::iterator iter;
1653 
1655  for (iter = txOpportunities.crdsaTxOpportunities.begin();
1656  iter != txOpportunities.crdsaTxOpportunities.end();
1657  iter++)
1658  {
1659  std::set<uint32_t>::iterator iterSet;
1660 
1662  for (iterSet = iter->second.begin(); iterSet != iter->second.end(); iterSet++)
1663  {
1665  if (!UpdateUsedRandomAccessSlots(superFrameId, allocationChannel, *iterSet))
1666  {
1669  NS_FATAL_ERROR(
1670  "SatUtMac::ScheduleCrdsaTransmission - Slot unavailable: " << *iterSet);
1671  }
1672  }
1673 
1675  NS_LOG_INFO("Creating replicas for packet " << (uint32_t)m_crdsaUniquePacketId);
1676  CreateCrdsaPacketInstances(allocationChannel, iter->second);
1677  }
1678 }
1679 
1680 void
1681 SatUtMac::CreateCrdsaPacketInstances(uint32_t allocationChannel, std::set<uint32_t> slots)
1682 {
1683  NS_LOG_FUNCTION(this << allocationChannel);
1684 
1685  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " AC: " << allocationChannel);
1686 
1687  Ptr<SatSuperframeConf> superframeConf =
1689  uint8_t frameId = superframeConf->GetRaChannelFrameId(allocationChannel);
1690  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
1691 
1694  Time superframeStartTime = Now();
1695 
1697  uint32_t payloadBytes = superframeConf->GetRaChannelTimeSlotPayloadInBytes(allocationChannel);
1698 
1700  payloadBytes -= m_randomAccess->GetCrdsaSignalingOverheadInBytes();
1701 
1702  if (payloadBytes < 1)
1703  {
1704  NS_FATAL_ERROR(
1705  "SatUtMac::CreateCrdsaPacketInstances - Not enough capacity in CRDSA payload");
1706  }
1707 
1712  {
1713  policy = SatUtScheduler::STRICT;
1714  }
1715  else
1716  {
1717  policy = SatUtScheduler::LOOSE;
1718  }
1719 
1723  payloadBytes,
1725  uint8_t(SatEnums::CONTROL_FID),
1726  policy,
1727  true);
1728 
1729  NS_LOG_INFO("Processing the packet container, fragments: " << uniq.size());
1730 
1731  if (!uniq.empty())
1732  {
1733  std::vector<std::pair<uint16_t, SatPhy::PacketContainer_t>> replicas;
1734  std::map<uint16_t, SatCrdsaReplicaTag> tags;
1735  std::set<uint32_t>::iterator iterSet;
1736 
1737  NS_LOG_INFO("Creating replicas for a packet");
1738 
1740  for (iterSet = slots.begin(); iterSet != slots.end(); iterSet++)
1741  {
1743  SatPhy::PacketContainer_t::const_iterator it = uniq.begin();
1744 
1745  for (; it != uniq.end(); ++it)
1746  {
1747  rep.push_back((*it)->Copy());
1748  NS_LOG_INFO(
1749  "Replica in slot: "
1750  << (*iterSet) << ", original (HL packet) fragment UID: " << (*it)->GetUid()
1751  << ", copied replica fragment (HL packet) UID: " << rep.back()->GetUid());
1752  }
1753 
1754  NS_LOG_INFO("One replica created");
1755 
1756  replicas.push_back(std::make_pair(*iterSet, rep));
1757  }
1758 
1759  NS_LOG_INFO("Creating replica tags");
1760 
1762  for (uint32_t i = 0; i < replicas.size(); i++)
1763  {
1764  SatCrdsaReplicaTag replicaTag;
1765 
1766  replicaTag.AddSlotId(replicas[i].first);
1767 
1768  NS_LOG_INFO("Own packet tag: " << replicas[i].first);
1769 
1770  for (uint32_t j = 0; j < replicas.size(); j++)
1771  {
1772  if (i != j)
1773  {
1774  replicaTag.AddSlotId(replicas[j].first);
1775 
1776  NS_LOG_INFO("Other packet tag: " << replicas[j].first);
1777  }
1778  }
1779  tags.insert(std::make_pair(replicas[i].first, replicaTag));
1780  }
1781 
1782  NS_LOG_INFO("Scheduling replicas");
1783 
1785  for (uint32_t i = 0; i < replicas.size(); i++)
1786  {
1787  for (uint32_t j = 0; j < replicas[i].second.size(); j++)
1788  {
1789  NS_LOG_INFO("Replica: " << i << ", fragment: " << j
1790  << ", key: " << replicas[i].first << ", tag: "
1791  << tags.at(replicas[i].first).GetSlotIds().at(0)
1792  << ", fragment (HL packet) UID: "
1793  << replicas[i].second.at(j)->GetUid());
1794 
1796  replicas[i].second.at(j)->AddPacketTag(tags.at(replicas[i].first));
1797  }
1798 
1800  Ptr<SatTimeSlotConf> timeSlotConf = frameConf->GetTimeSlotConf(replicas[i].first);
1801 
1803  Time slotDelay = superframeStartTime + timeSlotConf->GetStartTime();
1804  Time offset = slotDelay - Now();
1805 
1806  if (offset.IsStrictlyNegative())
1807  {
1808  NS_FATAL_ERROR("SatUtMac::CreateCrdsaPacketInstances - Invalid transmit time: "
1809  << offset.GetSeconds());
1810  }
1811 
1813  Ptr<SatWaveform> wf =
1814  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
1815  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
1816 
1818  uint32_t carrierId =
1820  frameId,
1821  timeSlotConf->GetCarrierId());
1822 
1826  txInfo.modCod = wf->GetModCod();
1827  txInfo.sliceId = 0;
1828  txInfo.fecBlockSizeInBytes = wf->GetPayloadInBytes();
1830  txInfo.waveformId = wf->GetWaveformId();
1832 
1834  offset = GetRealSendingTime(offset);
1835  if (offset >= Seconds(0))
1836  {
1837  Simulator::Schedule(offset,
1839  this,
1840  replicas[i].second,
1841  duration,
1842  carrierId,
1843  txInfo);
1844  }
1845  NS_LOG_INFO("Scheduled a replica in slot " << replicas[i].first << " with offset "
1846  << offset.GetSeconds());
1847  }
1848  replicas.clear();
1849  tags.clear();
1850 
1852  }
1853 }
1854 
1855 bool
1857  uint32_t allocationChannelId,
1858  uint32_t slotId)
1859 {
1860  NS_LOG_FUNCTION(this << superFrameId << allocationChannelId << slotId);
1861 
1862  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " SF: " << superFrameId
1863  << " AC: " << allocationChannelId << " slot: " << slotId);
1864 
1865  std::map<std::pair<uint32_t, uint32_t>, std::set<uint32_t>>::iterator iter;
1866  bool isSlotFree = false;
1867 
1869  RemovePastRandomAccessSlots(superFrameId);
1870 
1871  std::pair<uint32_t, uint32_t> key = std::make_pair(superFrameId, allocationChannelId);
1872 
1873  iter = m_usedRandomAccessSlots.find(key);
1874 
1875  if (iter == m_usedRandomAccessSlots.end())
1876  {
1877  std::set<uint32_t> txOpportunities{{slotId}};
1878  std::pair<std::map<std::pair<uint32_t, uint32_t>, std::set<uint32_t>>::iterator, bool>
1879  result;
1880  result = m_usedRandomAccessSlots.insert(std::make_pair(key, txOpportunities));
1881 
1882  if (result.second)
1883  {
1884  isSlotFree = true;
1885  NS_LOG_INFO("No saved SF, slot " << slotId << " saved in SF " << superFrameId);
1886  }
1887  else
1888  {
1889  NS_LOG_WARN("No saved SF but unable to create one");
1890  }
1891  }
1892  else
1893  {
1894  std::pair<std::set<uint32_t>::iterator, bool> result;
1895  result = iter->second.insert(slotId);
1896 
1897  if (result.second)
1898  {
1899  isSlotFree = true;
1900  NS_LOG_INFO("Saved SF exist, slot " << slotId << " saved in SF " << superFrameId);
1901  }
1902  else
1903  {
1904  NS_LOG_WARN("Saved SF exist but unable to add slot " << slotId);
1905  }
1906  }
1907  return isSlotFree;
1908 }
1909 
1910 void
1912 {
1913  NS_LOG_FUNCTION(this << superFrameId);
1914 
1915  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " SF: " << superFrameId);
1916 
1917  std::map<std::pair<uint32_t, uint32_t>, std::set<uint32_t>>::iterator iter;
1918 
1919  for (iter = m_usedRandomAccessSlots.begin(); iter != m_usedRandomAccessSlots.end();)
1920  {
1921  if (iter->first.first < superFrameId)
1922  {
1923  iter = m_usedRandomAccessSlots.erase(iter);
1924  }
1925  else
1926  {
1927  ++iter;
1928  }
1929  }
1930 }
1931 
1932 void
1934 {
1935  NS_LOG_FUNCTION(this);
1936 
1937  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress());
1938  std::cout << "UT: " << m_nodeInfo->GetMacAddress() << std::endl;
1939 
1940  for (auto& iter : m_usedRandomAccessSlots)
1941  {
1942  for (auto& slot : iter.second)
1943  {
1944  std::cout << "SF: " << iter.first.first << " AC: " << iter.first.second
1945  << " slot: " << slot << std::endl;
1946  }
1947  }
1948 }
1949 
1950 void
1952 {
1953  NS_LOG_FUNCTION(this);
1954 
1955  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress());
1956 
1957  if (m_timuInfo != nullptr)
1958  {
1959  NS_LOG_INFO("Applying TIM-U parameters received during the previous frame");
1960 
1961  Ptr<SatBeamScheduler> srcScheduler = m_beamSchedulerCallback(m_satId, m_beamId);
1962 
1963  NS_LOG_INFO("UT handover, old satellite is " << m_satId << ", old beam is " << m_beamId);
1964 
1965  m_beamId = m_timuInfo->GetBeamId();
1966  m_satId = m_timuInfo->GetSatId();
1967 
1968  NS_LOG_INFO("UT handover, new satellite is " << m_satId << ", new beam is " << m_beamId);
1969 
1972 
1973  Address satAddress = m_timuInfo->GetSatAddress();
1974  Mac48Address satAddress48 = Mac48Address::ConvertFrom(satAddress);
1975  if (satAddress48 != m_satelliteAddress)
1976  {
1977  SetSatelliteAddress(satAddress48);
1978  }
1979 
1980  Ptr<SatTopology> satTopology = Singleton<SatTopology>::Get();
1981 
1982  satTopology->UpdateUtSatAndBeam(m_node, m_satId, m_beamId);
1983  Ptr<Node> gwNode = satTopology->GetGwFromBeam(m_beamId);
1984  satTopology->UpdateGwConnectedToUt(m_node, gwNode);
1985 
1986  Mac48Address gwAddress =
1987  Singleton<SatTopology>::Get()->GetGwAddressInUt(m_nodeInfo->GetNodeId());
1988  SetGwAddress(gwAddress);
1989  m_routingUpdateCallback(m_nodeInfo->GetMacAddress(), m_gwAddress);
1990 
1992 
1993  Ptr<SatBeamScheduler> dstScheduler = m_beamSchedulerCallback(m_satId, m_beamId);
1994  srcScheduler->DisconnectUt(m_nodeInfo->GetMacAddress());
1995  dstScheduler->ConnectUt(m_nodeInfo->GetMacAddress());
1996 
1997  Ptr<SatIdMapper> satIdMapper = Singleton<SatIdMapper>::Get();
1998  satIdMapper->UpdateMacToSatId(m_nodeInfo->GetMacAddress(), m_satId);
1999  satIdMapper->UpdateMacToBeamId(m_nodeInfo->GetMacAddress(), m_beamId);
2000  satTopology->UpdateUtSatAndBeam(m_node, m_satId, m_beamId);
2002 
2004  {
2006  }
2007 
2008  m_handoverModule->HandoverFinished();
2009 
2010  m_tbtpContainer->Clear();
2012  m_timuInfo = nullptr;
2013  }
2014  else if (m_txCheckCallback())
2015  {
2016  NS_LOG_INFO("Tx is permitted");
2017 
2018  if (m_rcstState.GetState() == SatUtMacState::RcstState_t::HOLD_STANDBY)
2019  {
2021  }
2022 
2023  if (m_loggedOn && m_handoverModule != nullptr)
2024  {
2025  NS_LOG_INFO("UT checking for beam handover recommendation");
2026  if (m_handoverModule->CheckForHandoverRecommendation(m_satId, m_beamId))
2027  {
2029  {
2032  }
2034  {
2036  }
2038  {
2040  LogOff();
2041 
2042  Ptr<SatBeamScheduler> srcScheduler = m_beamSchedulerCallback(m_satId, m_beamId);
2043 
2044  m_satId = m_handoverModule->GetAskedSatId();
2045  m_beamId = m_handoverModule->GetAskedBeamId();
2046 
2047  Ptr<SatTopology> satTopology = Singleton<SatTopology>::Get();
2048 
2049  satTopology->UpdateUtSatAndBeam(m_node, m_satId, m_beamId);
2050  Ptr<Node> gwNode = satTopology->GetGwFromBeam(m_beamId);
2051  satTopology->UpdateGwConnectedToUt(m_node, gwNode);
2052 
2053  Address satAddress =
2054  m_beamSchedulerCallback(m_satId, m_beamId)->GetSatAddress();
2055  Mac48Address satAddress48 = Mac48Address::ConvertFrom(satAddress);
2056  if (satAddress48 != m_satelliteAddress)
2057  {
2058  SetSatelliteAddress(satAddress48);
2059  }
2060 
2061  Mac48Address gwAddress =
2062  Singleton<SatTopology>::Get()->GetGwAddressInUt(m_nodeInfo->GetNodeId());
2063  if (gwAddress != m_gwAddress)
2064  {
2065  SetGwAddress(gwAddress);
2066  m_updateGwAddressCallback(gwAddress);
2067  m_routingUpdateCallback(m_nodeInfo->GetMacAddress(), gwAddress);
2068  }
2070 
2071  Ptr<SatBeamScheduler> dstScheduler = m_beamSchedulerCallback(m_satId, m_beamId);
2072  srcScheduler->DisconnectUt(m_nodeInfo->GetMacAddress());
2073  dstScheduler->ConnectUt(m_nodeInfo->GetMacAddress());
2074 
2075  Ptr<SatIdMapper> satIdMapper = Singleton<SatIdMapper>::Get();
2076  satIdMapper->UpdateMacToSatId(m_nodeInfo->GetMacAddress(), m_satId);
2077  satIdMapper->UpdateMacToBeamId(m_nodeInfo->GetMacAddress(), m_beamId);
2078  satTopology->UpdateUtSatAndBeam(m_node, m_satId, m_beamId);
2080 
2082  {
2084  }
2085 
2086  m_tbtpContainer->Clear();
2088  m_nextLogonTransmissionPossible = Simulator::Now();
2089  }
2090  }
2091  }
2092 
2093  if (m_randomAccess != nullptr)
2094  {
2095  if (m_loggedOn)
2096  {
2097  // reset packet ID counter for this frame
2099 
2100  // execute CRDSA trigger
2102  }
2103  else if (m_useLogon)
2104  {
2106  if (Simulator::Now() > m_nextLogonTransmissionPossible)
2107  {
2108  // Do Logon
2110  }
2111  }
2112  }
2113  }
2114  else
2115  {
2116  NS_LOG_INFO("Tx is disabled");
2118  }
2119 
2121  NS_ASSERT_MSG(Now() < nextSuperFrameTxTime,
2122  "Scheduling next superframe start time to the past!");
2123 
2124  Time schedulingDelay = nextSuperFrameTxTime - Now();
2125  Time realDelay = GetRealSendingTime(schedulingDelay);
2126  if (realDelay == Seconds(0))
2127  {
2128  schedulingDelay += m_superframeSeq->GetDuration(SatConstVariables::SUPERFRAME_SEQUENCE);
2129  }
2130  Simulator::Schedule(GetRealSendingTime(schedulingDelay), &SatUtMac::DoFrameStart, this);
2131 }
2132 
2133 Time
2135 {
2136  if (m_deltaNcr == 0) // For some reason returning t-0 is different than returning t...
2137  {
2138  return t;
2139  }
2140 
2141  uint32_t driftTicks = (t + Simulator::Now()).GetMicroSeconds() * m_clockDrift / 1000000;
2142  int32_t deltaTicks = m_deltaNcr - driftTicks;
2143  Time deltaTime = NanoSeconds(deltaTicks * 1000 / 27.0);
2144 
2145  return t - deltaTime;
2146 }
2147 
2149  uint32_t satId,
2150  Address satAddress,
2151  Address gwAddress)
2152  : m_beamId(beamId),
2153  m_satId(satId),
2154  m_satAddress(satAddress),
2155  m_gwAddress(gwAddress)
2156 {
2157  NS_LOG_FUNCTION(this << beamId << satAddress << gwAddress);
2158 }
2159 
2160 uint32_t
2162 {
2163  NS_LOG_FUNCTION(this);
2164  return m_beamId;
2165 }
2166 
2167 uint32_t
2169 {
2170  NS_LOG_FUNCTION(this);
2171  return m_satId;
2172 }
2173 
2174 Address
2176 {
2177  NS_LOG_FUNCTION(this);
2178  return m_satAddress;
2179 }
2180 
2181 Address
2183 {
2184  NS_LOG_FUNCTION(this);
2185  return m_gwAddress;
2186 }
2187 
2190 {
2191  NS_LOG_FUNCTION(this);
2192  return m_rcstState.GetState();
2193 }
2194 
2195 void
2197  uint32_t payloadBytes,
2199  uint8_t rcIndex,
2201  bool randomAccessChannel)
2202 {
2203  NS_LOG_INFO(this << payloadBytes << type << rcIndex << policy << randomAccessChannel);
2204 
2206  if ((m_handoverState == NO_HANDOVER &&
2207  (randomAccessChannel || m_firstTransmittableSuperframeId <= superFrameId)) ||
2208  (randomAccessChannel && m_handoverState != HANDOVER_RECOMMENDATION_SENT))
2209  {
2210  NS_LOG_INFO("Regular scheduling");
2211  m_utScheduler->DoScheduling(packets, payloadBytes, type, rcIndex, policy);
2212  }
2213  else
2214  {
2215  NS_LOG_INFO("Handover recommendation sent, force control packets only");
2216  m_utScheduler->DoScheduling(packets,
2217  payloadBytes,
2221 
2222  // Remove every control packets except handover requests
2223  SatPhy::PacketContainer_t::iterator it = packets.begin();
2224  while (it != packets.end())
2225  {
2226  SatControlMsgTag ctrlTag;
2227  bool success = (*it)->PeekPacketTag(ctrlTag);
2228 
2229  if (success && ctrlTag.GetMsgType() == SatControlMsgTag::SAT_HR_CTRL_MSG)
2230  {
2231  ++it;
2232  }
2233  else
2234  {
2235  it = packets.erase(it);
2236  }
2237  }
2238  }
2239 }
2240 
2241 } // namespace ns3
This class implements a tag that carries the satellite MAC of GW and UT.
void SetE2ESourceAddress(Mac48Address e2eSourceAddress)
Set E2E source MAC address.
Mac48Address GetE2ESourceAddress(void) const
Get E2E source MAC address.
void SetE2EDestAddress(Mac48Address e2eDestAddress)
Set E2E destination MAC address.
Mac48Address GetE2EDestAddress(void) const
Get E2E destination MAC address.
This class implements a tag that is used to identify control messages (packages).
SatControlMsgType_t
Definition for different types of control messages.
@ SAT_LOGON_RESPONSE_CTRL_MSG
SAT_LOGON_RESPONSE_CTRL_MSG.
@ SAT_SLICE_CTRL_MSG
SAT_SLICE_CTRL_MSG.
@ SAT_TIMU_CTRL_MSG
SAT_TIMU_CTRL_MSG.
@ SAT_LOGOFF_CTRL_MSG
SAT_LOGOFF CTRL_MSG.
@ SAT_NON_CTRL_MSG
SAT_NON_CTRL_MSG.
@ SAT_CMT_CTRL_MSG
SAT_CMT_CTRL_MSG.
@ SAT_TBTP_CTRL_MSG
SAT_TBTP_CTRL_MSG.
@ SAT_NCR_CTRL_MSG
SAT_NCR_CTRL_MSG.
virtual uint32_t GetMsgId() const
Get message type specific identifier.
SatControlMsgType_t GetMsgType(void) const
Get type of the control message.
This class implements a tag that carries information about the slot IDs of CRDSA packet replicas.
SatEncapPduStatusTag is used temporarily to tag packets with the fragmentation status in the encapsul...
void SetStatus(uint8_t status)
Set PDU status.
RandomAccessTriggerType_t
The defined random access trigger types.
@ LOG_WARNING
LOG_WARNING.
Definition: satellite-log.h:66
Base MAC class for SatNetDevices.
Definition: satellite-mac.h:57
void RxTraces(SatPhy::PacketContainer_t packets)
Invoke the Rx trace source for each received packet.
void SetBeamId(uint32_t beamId)
Set beam ID of the object.
SatMac::BeamSchedulerCallback m_beamSchedulerCallback
Callback to get the SatBeamScheduler linked to a beam ID.
SatMac::RoutingUpdateCallback m_routingUpdateCallback
Callback to update routing and ARP tables after a beam handover.
TracedCallback< Time, SatEnums::SatPacketEvent_t, SatEnums::SatNodeType_t, uint32_t, Mac48Address, SatEnums::SatLogLevel_t, SatEnums::SatLinkDir_t, std::string > m_packetTrace
Trace callback used for packet tracing.
Address m_satelliteAddress
MAC address of satellite on other side of the link.
virtual void SetNodeInfo(Ptr< SatNodeInfo > nodeInfo)
Set the node info.
void DoDispose(void)
Dispose of SatMac.
SatMac::ReceiveCallback m_rxCallback
The upper layer package receive callback.
bool m_ncrV2
Use of version 2 of NCR dates.
bool m_isRegenerative
Indicate if satellite is regeneration (at least LINK level) for TX.
void SetSatId(uint32_t satId)
Set sat ID of the object.
Ptr< SatHandoverModule > m_handoverModule
Module used to perform handovers.
SatMac::ReadCtrlMsgCallback m_readCtrlCallback
The read control message callback.
Ptr< SatNodeInfo > m_nodeInfo
Node info containing node related information, such as node type, node id and MAC address (of the Sat...
SatEnums::RegenerationMode_t m_returnLinkRegenerationMode
Regeneration mode on return link.
virtual void SendPacket(SatPhy::PacketContainer_t packets, uint32_t carrierId, Time duration, SatSignalParameters::txInfo_s txInfo)
Send packets to lower layer by using a callback.
SatMac::UpdateIslCallback m_updateIslCallback
The update ISL routes callback.
This class implements a tag that carries the satellite MAC specific information, such as source and d...
void SetDestAddress(Mac48Address dest)
Set destination MAC address.
Mac48Address GetSourceAddress(void) const
Get source MAC address.
Mac48Address GetDestAddress(void) const
Get destination MAC address.
void SetSourceAddress(Mac48Address source)
Set source MAC address.
SatSignalParameters::PacketsInBurst_t PacketContainer_t
Define PacketContainer in SatPhy.
Definition: satellite-phy.h:79
@ CONFIG_TYPE_4
Configuration type 4 (ESSA)
bool HasScheduledTimeSlots()
Method of checking whether the UT has been scheduled time slots into the future.
std::pair< uint8_t, DaTimeSlotConfContainer_t > DaTimeSlotInfoItem_t
Item for DA time slot information.
SatTimeSlotType_t
Types for time slot.
@ SLOT_TYPE_TRC
Control or traffic slot.
SatTimuInfo(uint32_t beamId, uint32_t satId, Address satAddress, Address gwAddress)
void SetRandomAccess(Ptr< SatRandomAccess > randomAccess)
Set the random access module.
Ptr< SatSuperframeSeq > m_superframeSeq
Used superframe sequence for the return link.
Callback< bool > TxCheckCallback
Callback to check if TX is operational.
virtual void ReceiveQueueEventEssa(SatQueue::QueueEvent_t event, uint8_t rcIndex)
Receive a queue event:
Ptr< SatTbtpContainer > m_tbtpContainer
Container for storing all the TBTP information related to this UT.
virtual void Receive(SatPhy::PacketContainer_t packets, Ptr< SatSignalParameters >)
Receive packet from lower layer.
Time m_guardTime
Guard time for time slots.
void DoEssaTransmit(Time duration, Ptr< SatWaveform > waveform, uint32_t carrierId, uint8_t rcIndex, SatUtScheduler::SatCompliancePolicy_t policy=SatUtScheduler::LOOSE)
Notify the upper layer about the ESSA Tx opportunity.
static TypeId GetTypeId(void)
Derived from Object.
int64_t m_deltaNcr
Correction to apply to NCR dates.
void PrintUsedRandomAccessSlots()
uint32_t m_beamId
ID of beam for UT.
uint32_t m_handoverMessagesCount
Time m_maxWaitingTimeLogonResponse
Timeout for waiting for a response for a logon message.
std::pair< bool, uint32_t > SearchFrameForAvailableSlot(Time superframeStartTime, Ptr< SatFrameConf > frameConf, uint32_t timeSlotCount, uint32_t superFrameId, uint32_t allocationChannel)
Callback< void, uint32_t, uint32_t > HandoverCallback
Callback to reconfigure physical layer during handover.
void SetAssignedDaResourcesCallback(SatUtMac::AssignedDaResourcesCallback cb)
Set the assigned DA resources callback.
Mac48Address m_gwAddress
SatUtMac::HandoverCallback m_handoverCallback
The physical layer handover callback.
SatUtMacState::RcstState_t GetRcstState() const
uint64_t m_ncr
NCR value of last NCR control message.
void SendLogon(Ptr< Packet > packet)
Receive a logon message to transmit /param packet The logon packet to send.
virtual void SetSatelliteAddress(Address satelliteAddress)
Set the satellite MAC address on the other side of this link (if regenerative satellite).
void ScheduleTimeSlots(Ptr< SatTbtpMessage > tbtp)
Schedules time slots according to received TBTP message.
void SetHandoverCallback(SatUtMac::HandoverCallback cb)
Method to set handover callback.
virtual void ReceiveQueueEvent(SatQueue::QueueEvent_t event, uint8_t rcIndex)
Receive a queue event:
Callback< void, Mac48Address > UpdateGwAddressCallback
Callback to update GW address to SatRequestManager.
Callback< void > SendLogonCallback
Callback to send a logon message to the gateway.
SatUtMac::SliceSubscriptionCallback m_sliceSubscriptionCallback
Tx checking callback.
Time GetRealSendingTime(Time t)
Compute real sending time of UT based on last NCR reception date and clock drift.
void ScheduleEssaTransmission(uint32_t allocationChannel)
Function for scheduling the ESSA transmissions.
virtual TypeId GetInstanceTypeId(void) const
Derived from Object.
SatUtMac::UpdateAddressAndIdentifierCallback m_updateAddressAndIdentifierCallback
Callback to update addresses in statistics helpers.
void SetTxCheckCallback(SatUtMac::TxCheckCallback cb)
Set the TX check callback.
Ptr< SatTimuInfo > m_timuInfo
void RemovePastRandomAccessSlots(uint32_t superFrameId)
Function for removing the past used RA slots.
void ScheduleCrdsaTransmission(uint32_t allocationChannel, SatRandomAccess::RandomAccessTxOpportunities_s txOpportunities)
Function for scheduling the CRDSA transmissions.
Callback< Time > TimingAdvanceCallback
uint32_t m_maxHandoverMessagesSent
void SetUpdateGwAddressCallback(SatUtMac::UpdateGwAddressCallback cb)
Set the gw update callback.
SatUtMac::UpdateGwAddressCallback m_updateGwAddressCallback
Callback for sending a logon message.
uint32_t m_firstTransmittableSuperframeId
std::map< std::pair< uint32_t, uint32_t >, std::set< uint32_t > > m_usedRandomAccessSlots
A container for storing the used RA slots in each frame and allocation channel.
void SetSliceSubscriptionCallback(SatUtMac::SliceSubscriptionCallback cb)
Get sliec subscription info from MAC layer.
void DoSlottedAlohaTransmit(Time duration, Ptr< SatWaveform > waveform, uint32_t carrierId, uint8_t rcIndex, SatUtScheduler::SatCompliancePolicy_t policy=SatUtScheduler::LOOSE)
Notify the upper layer about the Slotted ALOHA Tx opportunity.
uint32_t m_crdsaUniquePacketId
CRDSA packet ID (per frame)
Time m_lastNcrDateReceived
Reception date of last NCR control message.
void SetSendLogonCallback(SatUtMac::SendLogonCallback cb)
Set the logon callback.
~SatUtMac()
Destroy a SatUtMac.
Time m_windowInitLogon
The initial max time to wait when sending a logon message.
Time GetNextSuperFrameTxTime(uint8_t superFrameSeqId) const
Get Tx time for the next possible superframe.
SatUtMac::GatewayUpdateCallback m_gatewayUpdateCallback
Gateway address update callback.
void ScheduleSlottedAlohaTransmission(uint32_t allocationChannel)
Function for scheduling the Slotted ALOHA transmissions.
HandoverState_t m_handoverState
uint32_t GetCurrentSuperFrameId(uint8_t superFrameSeqId) const
void SetRaChannel(uint32_t raChannel)
Set RA channel assigned for this UT.
Mac48Address GetGwAddress()
Get address of the GW (or its MAC) serving this UT.
std::queue< Time > m_receptionDates
Store last 3 packets reception date, to be associated to NCR dates.
void ExtractPacketsToSchedule(SatPhy::PacketContainer_t &packets, uint32_t payloadBytes, SatTimeSlotConf::SatTimeSlotType_t type, uint8_t rcIndex, SatUtScheduler::SatCompliancePolicy_t policy, bool randomAccessChannel)
Extract packets from the underlying queue and put them in the provided container.
SatUtMacState m_rcstState
Time m_nextPacketTime
Next time when a next ESSA packet can be safely sent.
uint32_t m_logonChannel
RA channel dedicated to logon messages.
void ReceiveSignalingPacket(Ptr< Packet > packet)
Signaling packet receiver, which handles all the signaling packet receptions.
void SetTimingAdvanceCallback(SatUtMac::TimingAdvanceCallback cb)
Set the timing advance callback.
SatPhy::PacketContainer_t FetchPackets(uint32_t payloadBytes, SatTimeSlotConf::SatTimeSlotType_t type, uint8_t rcIndex, SatUtScheduler::SatCompliancePolicy_t policy)
Callback< void, uint8_t, uint32_t > AssignedDaResourcesCallback
Callback for informing the amount of dedicated access bytes received from TBTP.
TracedCallback< uint32_t > m_tbtpResourcesTrace
Assigned TBTP resources in superframe for this UT (in bytes).
std::pair< bool, uint32_t > FindNextAvailableRandomAccessSlot(Time opportunityOffset, Ptr< SatFrameConf > frameConf, uint32_t timeSlotCount, uint32_t superFrameId, uint32_t allocationChannel)
bool m_crdsaOnlyForControl
Planned CRDSA usage:
void DoDispose(void)
Dispose of SatUtMac.
uint32_t GetNextRandomAccessAllocationChannel()
Function for selecting the allocation channel for the current RA evaluation.
void SetLogonChannel(uint32_t channelId)
void ScheduleDaTxOpportunity(Time transmitDelay, Time duration, Ptr< SatWaveform > wf, Ptr< SatTimeSlotConf > tsConf, uint32_t carrierId)
Schdules one Tx opportunity, i.e.
SatUtMac()
Default constructor, which is not used.
Ptr< Node > m_node
Node containing this MAC.
Ptr< SatUtScheduler > m_utScheduler
UT scheduler.
bool UpdateUsedRandomAccessSlots(uint32_t superFrameId, uint32_t allocationChannel, uint32_t slot)
Function for updating the used RA slots.
void TransmitPackets(SatPhy::PacketContainer_t packets, Time duration, uint32_t carrierId, SatSignalParameters::txInfo_s txInfo)
void CreateCrdsaPacketInstances(uint32_t allocationChannel, std::set< uint32_t > slots)
Ptr< SatRandomAccess > m_randomAccess
RA main module.
bool m_isRandomAccessScheduled
Flag that indicates if a method DoRandomAccess is scheduled for asynchronous access.
TimingAdvanceCallback m_timingAdvanceCb
Callback for getting the timing advance information.
uint32_t m_satId
ID of sat for UT.
bool ControlMsgTransmissionPossible() const
Method to check whether a transmission of a control msg is somewhat possible.
int32_t m_clockDrift
Clock drift (number of ticks per second)
void DoTransmit(Time duration, uint32_t carrierId, Ptr< SatWaveform > wf, Ptr< SatTimeSlotConf > tsConf, SatUtScheduler::SatCompliancePolicy_t policy=SatUtScheduler::LOOSE)
Notify the upper layer about the Tx opportunity.
void DoFrameStart()
Function which is executed at every frame start.
Callback< void, Mac48Address > GatewayUpdateCallback
Callback to update gateway address after handover.
Time m_nextLogonTransmissionPossible
Instant when a logon message can be transmitted.
Ptr< UniformRandomVariable > m_waitingTimeLogonRng
The random generator for waiting transmission time.
void SetGwAddress(Mac48Address gwAddress)
Set address of the GW (or its MAC) serving this UT.
bool LogonMsgTransmissionPossible() const
Method to check whether a transmission of a logon msg is somewhat possible.
Time GetCurrentSuperFrameStartTime(uint8_t superFrameSeqId) const
Get start time for the current superframe.
void SetGatewayUpdateCallback(SatUtMac::GatewayUpdateCallback cb)
Method to set the gateway address update callback.
bool m_useLogon
Should logon be simulated?
virtual void SetNodeInfo(Ptr< SatNodeInfo > nodeInfo)
Set the node info.
uint32_t m_sendLogonTries
Number of times a logon message has been sent without response.
uint32_t m_raChannel
RA channel assigned to the UT.
uint32_t GetRaChannel() const
Get RA channel assigned for this UT.
void SetUpdateAddressAndIdentifierCallback(SatUtMac::UpdateAddressAndIdentifierCallback cb)
Set the callback to update addresses in statistics helpers.
void DoRandomAccess(SatEnums::RandomAccessTriggerType_t randomAccessTriggerType)
Do random access evaluation for Tx opportunities.
Callback< void, uint8_t > SliceSubscriptionCallback
Callback to check if TX is operational.
Callback< void, Ptr< Node > > UpdateAddressAndIdentifierCallback
Callback to update addresses in statistics helpers.
Ptr< UniformRandomVariable > m_uniformRandomVariable
Uniform random variable distribution generator.
AssignedDaResourcesCallback m_assignedDaResourcesCallback
Callback for informing the assigned TBTP resources.
SatUtMac::SendLogonCallback m_sendLogonCallback
Callback for sending a logon message.
bool m_loggedOn
UT is logged on.
SatUtMac::TxCheckCallback m_txCheckCallback
Tx checking callback.
Class handling UT Mac states and transitions.
void SwitchToReadyForTdmaSync()
Change state to READY_FOR_TDMA_SYNC.
void SetLogOffCallback(LogOffCallback cb)
Set logOff callback.
void SwitchToOffStandby()
Change state to OFF_STANDBY.
void NcrControlMessageReceived()
Inform the state diagram that a NCR message has been received.
void SwitchToReadyForLogon()
Change state to READY_FOR_LOGON.
RcstState_t GetState() const
Get the current state.
void SwitchToTdmaSync()
Change state to TDMA_SYNC.
void SwitchToHoldStandby()
Change state to HOLD_STANDBY.
bool IsNcrTimeout() const
Check if NCR m_ncrSyncTimeout has been reached.
SatCompliancePolicy_t
Enum describing the wanted scheduler policy.
static std::string GetPacketInfo(const Ptr< const Packet > p)
Get packet information in std::string for printing purposes.
constexpr uint8_t SUPERFRAME_SEQUENCE
Used superframe sequence in the RTN link.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
std::map< uint32_t, std::set< uint32_t > > crdsaTxOpportunities
Struct for storing the packet specific Tx information.