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 
29 #include "satellite-frame-conf.h"
30 #include "satellite-log.h"
31 #include "satellite-node-info.h"
35 #include "satellite-utils.h"
37 
38 #include <ns3/boolean.h>
39 #include <ns3/log.h>
40 #include <ns3/mac48-address.h>
41 #include <ns3/packet.h>
42 #include <ns3/pointer.h>
43 #include <ns3/random-variable-stream.h>
44 #include <ns3/simulator.h>
45 #include <ns3/singleton.h>
46 
47 NS_LOG_COMPONENT_DEFINE("SatUtMac");
48 
49 namespace ns3
50 {
51 
52 NS_OBJECT_ENSURE_REGISTERED(SatUtMac);
53 
54 TypeId
56 {
57  static TypeId tid =
58  TypeId("ns3::SatUtMac")
59  .SetParent<SatMac>()
60  .AddConstructor<SatUtMac>()
61  .AddAttribute("MaxHandoverMessages",
62  "Max amount of handover messages to send without a handover response "
63  "before loging off",
64  UintegerValue(20),
65  MakeUintegerAccessor(&SatUtMac::m_maxHandoverMessagesSent),
66  MakeUintegerChecker<uint32_t>())
67  .AddAttribute("SuperframeSequence",
68  "Superframe sequence containing information of superframes.",
69  PointerValue(),
70  MakePointerAccessor(&SatUtMac::m_superframeSeq),
71  MakePointerChecker<SatSuperframeSeq>())
72  .AddAttribute("GuardTime",
73  "Guard time in return link",
74  TimeValue(MicroSeconds(1)),
75  MakeTimeAccessor(&SatUtMac::m_guardTime),
76  MakeTimeChecker())
77  .AddAttribute("Scheduler",
78  "UT scheduler used by this Sat UT MAC.",
79  PointerValue(),
80  MakePointerAccessor(&SatUtMac::m_utScheduler),
81  MakePointerChecker<SatUtScheduler>())
82  .AddAttribute("WindowInitLogon",
83  "The initial window for logon waiting time before transmission.",
84  TimeValue(Seconds(20)),
85  MakeTimeAccessor(&SatUtMac::m_windowInitLogon),
86  MakeTimeChecker())
87  .AddAttribute("MaxWaitingTimeLogonResponse",
88  "Timeout for waiting for a response for a logon message.",
89  TimeValue(Seconds(1)),
90  MakeTimeAccessor(&SatUtMac::m_maxWaitingTimeLogonResponse),
91  MakeTimeChecker())
92  .AddAttribute("ClockDrift",
93  "Clock drift (number of ticks per second).",
94  IntegerValue(0),
95  MakeIntegerAccessor(&SatUtMac::m_clockDrift),
96  MakeIntegerChecker<int32_t>())
97  .AddTraceSource("DaResourcesTrace",
98  "Assigned dedicated access resources in return link to this UT.",
99  MakeTraceSourceAccessor(&SatUtMac::m_tbtpResourcesTrace),
100  "ns3::SatUtMac::TbtpResourcesTraceCallback");
101  return tid;
102 }
103 
104 TypeId
106 {
107  NS_LOG_FUNCTION(this);
108 
109  return GetTypeId();
110 }
111 
113  : SatMac(),
114  m_satId(0),
115  m_beamId(),
116  m_superframeSeq(),
117  m_timingAdvanceCb(),
118  m_randomAccess(NULL),
119  m_guardTime(MicroSeconds(1)),
120  m_raChannel(0),
121  m_logonChannel(0),
122  m_loggedOn(true),
123  m_useLogon(false),
124  m_sendLogonTries(0),
125  m_windowInitLogon(Seconds(20)),
126  m_maxWaitingTimeLogonResponse(Seconds(1)),
127  m_waitingTimeLogonRng(CreateObject<UniformRandomVariable>()),
128  m_nextLogonTransmissionPossible(Seconds(0)),
129  m_crdsaUniquePacketId(1),
130  m_crdsaOnlyForControl(false),
131  m_nextPacketTime(Now()),
132  m_isRandomAccessScheduled(false),
133  m_timuInfo(0),
134  m_rcstState(SatUtMacState()),
135  m_lastNcrDateReceived(Seconds(0)),
136  m_ncr(0),
137  m_deltaNcr(0),
138  m_clockDrift(0),
139  m_handoverState(NO_HANDOVER),
140  m_handoverMessagesCount(0),
141  m_maxHandoverMessagesSent(20),
142  m_firstTransmittableSuperframeId(0),
143  m_handoverCallback(),
144  m_gatewayUpdateCallback(),
145  m_beamCheckerCallback(),
146  m_askedBeamCallback(),
147  m_txCheckCallback(),
148  m_sliceSubscriptionCallback(),
149  m_sendLogonCallback(),
150  m_updateGwAddressCallback(),
151  m_beamScheculerCallback()
152 {
153  NS_LOG_FUNCTION(this);
154 
155  // default constructor should not be used
156  NS_FATAL_ERROR("SatUtMac::SatUtMac - Constructor not in use");
157 }
158 
159 SatUtMac::SatUtMac(uint32_t satId,
160  uint32_t beamId,
161  Ptr<SatSuperframeSeq> seq,
162  SatEnums::RegenerationMode_t forwardLinkRegenerationMode,
163  SatEnums::RegenerationMode_t returnLinkRegenerationMode,
164  bool crdsaOnlyForControl)
165  : SatMac(satId, beamId, forwardLinkRegenerationMode, returnLinkRegenerationMode),
166  m_satId(satId),
167  m_beamId(beamId),
168  m_superframeSeq(seq),
169  m_timingAdvanceCb(),
170  m_guardTime(MicroSeconds(1)),
171  m_raChannel(0),
172  m_logonChannel(0),
173  m_loggedOn(true),
174  m_useLogon(false),
175  m_sendLogonTries(0),
176  m_windowInitLogon(Seconds(20)),
177  m_maxWaitingTimeLogonResponse(Seconds(1)),
178  m_waitingTimeLogonRng(CreateObject<UniformRandomVariable>()),
179  m_nextLogonTransmissionPossible(Seconds(0)),
180  m_crdsaUniquePacketId(1),
181  m_crdsaOnlyForControl(crdsaOnlyForControl),
182  m_nextPacketTime(Now()),
183  m_isRandomAccessScheduled(false),
184  m_timuInfo(0),
185  m_rcstState(SatUtMacState()),
186  m_lastNcrDateReceived(Seconds(0)),
187  m_ncr(0),
188  m_deltaNcr(0),
189  m_clockDrift(0),
190  m_handoverState(NO_HANDOVER),
191  m_handoverMessagesCount(0),
192  m_maxHandoverMessagesSent(20),
193  m_firstTransmittableSuperframeId(0),
194  m_handoverCallback(),
195  m_gatewayUpdateCallback(),
196  m_beamCheckerCallback(),
197  m_askedBeamCallback(),
198  m_txCheckCallback(),
199  m_sliceSubscriptionCallback(),
200  m_sendLogonCallback(),
201  m_updateGwAddressCallback(),
202  m_beamScheculerCallback()
203 {
204  NS_LOG_FUNCTION(this);
205 
206  m_uniformRandomVariable = CreateObject<UniformRandomVariable>();
207  m_tbtpContainer = CreateObject<SatTbtpContainer>(m_superframeSeq);
208 }
209 
211 {
212  NS_LOG_FUNCTION(this);
213 
214  m_randomAccess = NULL;
215  m_tbtpContainer = NULL;
216  m_timuInfo = NULL;
217 }
218 
219 void
221 {
222  NS_LOG_FUNCTION(this);
223 
224  m_timingAdvanceCb.Nullify();
225  m_handoverCallback.Nullify();
226  m_gatewayUpdateCallback.Nullify();
227  m_beamCheckerCallback.Nullify();
228  m_askedBeamCallback.Nullify();
229  m_txCheckCallback.Nullify();
230  m_sliceSubscriptionCallback.Nullify();
231  m_sendLogonCallback.Nullify();
232  m_updateGwAddressCallback.Nullify();
233  m_beamScheculerCallback.Nullify();
234  m_tbtpContainer->DoDispose();
235  m_utScheduler->DoDispose();
236  m_utScheduler = NULL;
237 
239 }
240 
241 void
243 {
244  NS_LOG_FUNCTION(this << &cb);
245  m_handoverCallback = cb;
246 }
247 
248 void
250 {
251  NS_LOG_FUNCTION(this << &cb);
253 }
254 
255 void
257 {
258  NS_LOG_FUNCTION(this << &cb);
260 }
261 
262 void
264 {
265  NS_LOG_FUNCTION(this << &cb);
266  m_askedBeamCallback = cb;
267 }
268 
269 void
271 {
272  NS_LOG_FUNCTION(this << &cb);
273 
274  m_txCheckCallback = cb;
275 }
276 
277 void
279 {
280  NS_LOG_FUNCTION(this << &cb);
281 
283 }
284 
285 void
287 {
288  NS_LOG_FUNCTION(this << &cb);
289 
290  m_sendLogonCallback = cb;
291 }
292 
293 void
295 {
296  NS_LOG_FUNCTION(this << &cb);
297 
299 }
300 
301 void
303 {
304  NS_LOG_FUNCTION(this << &cb);
305 
307 }
308 
309 void
310 SatUtMac::SetSatelliteAddress(Address satelliteAddress)
311 {
312  m_satelliteAddress = satelliteAddress;
313  m_isRegenerative = true;
314 }
315 
316 Mac48Address
318 {
319  NS_LOG_FUNCTION(this);
320 
321  return m_gwAddress;
322 }
323 
324 void
325 SatUtMac::SetGwAddress(Mac48Address gwAddress)
326 {
327  NS_LOG_FUNCTION(this << gwAddress);
328 
329  m_gatewayUpdateCallback(gwAddress);
330  m_gwAddress = gwAddress;
331 }
332 
333 void
334 SatUtMac::SetNodeInfo(Ptr<SatNodeInfo> nodeInfo)
335 {
336  NS_LOG_FUNCTION(this << nodeInfo);
337 
338  m_tbtpContainer->SetMacAddress(nodeInfo->GetMacAddress());
339  m_utScheduler->SetNodeInfo(nodeInfo);
340  SatMac::SetNodeInfo(nodeInfo);
341 }
342 
343 void
345 {
346  NS_LOG_FUNCTION(this);
347  m_loggedOn = false;
350 }
351 
352 void
353 SatUtMac::SetLogonChannel(uint32_t channelId)
354 {
355  NS_LOG_FUNCTION(this);
356  m_logonChannel = channelId;
357  m_useLogon = true;
358 }
359 
360 void
361 SatUtMac::SetRaChannel(uint32_t raChannel)
362 {
363  NS_LOG_FUNCTION(this << raChannel);
364 
365  m_raChannel = raChannel;
366 }
367 
368 uint32_t
370 {
371  NS_LOG_FUNCTION(this);
372 
373  return m_raChannel;
374 }
375 
376 void
377 SatUtMac::SetRandomAccess(Ptr<SatRandomAccess> randomAccess)
378 {
379  NS_LOG_FUNCTION(this);
380 
381  m_randomAccess = randomAccess;
382  m_randomAccess->SetIsDamaAvailableCallback(
384 }
385 
386 bool
388 {
389  NS_LOG_FUNCTION(this);
390 
391  bool da = m_tbtpContainer->HasScheduledTimeSlots();
392  bool ra = (m_randomAccess != NULL);
393  if (m_useLogon)
394  {
395  ra = ra && (m_raChannel != m_logonChannel);
396  }
397  return da || ra;
398 }
399 
400 bool
402 {
403  NS_LOG_FUNCTION(this);
404 
405  bool stateCorrect = (m_rcstState.GetState() == SatUtMacState::RcstState_t::READY_FOR_LOGON);
406  bool ncrReceived = !m_rcstState.IsNcrTimeout();
407 
408  return m_useLogon && stateCorrect && ncrReceived;
409 }
410 
411 void
413 {
414  NS_LOG_FUNCTION(this << &cb);
415 
416  m_timingAdvanceCb = cb;
417 
420 
421  if (Now() >= nextSuperFrameTxTime)
422  {
423  NS_FATAL_ERROR("Scheduling next superframe start time to the past!");
424  }
425 
426  Time schedulingDelay = nextSuperFrameTxTime - Now();
427 
428  Simulator::Schedule(GetRealSendingTime(schedulingDelay), &SatUtMac::DoFrameStart, this);
429 }
430 
431 void
433 {
434  NS_LOG_FUNCTION(this << &cb);
435 
437 }
438 
439 Time
440 SatUtMac::GetNextSuperFrameTxTime(uint8_t superFrameSeqId) const
441 {
442  NS_LOG_FUNCTION(this << (uint32_t)superFrameSeqId);
443 
444  Time timingAdvance = m_timingAdvanceCb();
445  Time txTime =
446  Singleton<SatRtnLinkTime>::Get()->GetNextSuperFrameTxTime(superFrameSeqId, timingAdvance);
447  return txTime;
448 }
449 
450 Time
451 SatUtMac::GetCurrentSuperFrameStartTime(uint8_t superFrameSeqId) const
452 {
453  NS_LOG_FUNCTION(this << (uint32_t)superFrameSeqId);
454 
455  Time timingAdvance = m_timingAdvanceCb();
456  Time txTime = Singleton<SatRtnLinkTime>::Get()->GetCurrentSuperFrameTxTime(superFrameSeqId,
457  timingAdvance);
458  return txTime;
459 }
460 
461 uint32_t
462 SatUtMac::GetCurrentSuperFrameId(uint8_t superFrameSeqId) const
463 {
464  NS_LOG_FUNCTION(this << (uint32_t)superFrameSeqId);
465 
466  return Singleton<SatRtnLinkTime>::Get()->GetCurrentSuperFrameCount(superFrameSeqId,
468 }
469 
470 void
471 SatUtMac::ScheduleTimeSlots(Ptr<SatTbtpMessage> tbtp)
472 {
473  NS_LOG_FUNCTION(this << tbtp);
474  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " received TBTP "
475  << tbtp->GetSuperframeCounter());
476 
487  ->GetConfigType() == SatSuperframeConf::CONFIG_TYPE_4)
488  {
489  return;
490  }
491 
492  Time timingAdvance = m_timingAdvanceCb();
493  Time txTime =
494  Singleton<SatRtnLinkTime>::Get()->GetSuperFrameTxTime(tbtp->GetSuperframeSeqId(),
495  tbtp->GetSuperframeCounter(),
496  timingAdvance);
497 
498  // The delay compared to Now when to start the transmission of this superframe
499  Time startDelay = txTime - Simulator::Now();
500 
501  // Add TBTP to a specific container
502  m_tbtpContainer->Add(txTime, tbtp);
503 
504  // if the calculated start time of the superframe is already in the past
505  if (txTime < Simulator::Now())
506  {
507  NS_FATAL_ERROR("UT: " << m_nodeInfo->GetMacAddress() << " received TBTP "
508  << tbtp->GetSuperframeCounter()
509  << ", which should have been sent already in the past");
510  }
511 
512  NS_LOG_INFO("Time to start sending the superframe for this UT: " << txTime.GetSeconds());
513  NS_LOG_INFO("Waiting delay before the superframe start: " << startDelay.GetSeconds());
514 
515  SatTbtpMessage::DaTimeSlotInfoItem_t info = tbtp->GetDaTimeslots(m_nodeInfo->GetMacAddress());
516 
517  // Counters for allocated TBTP resources
518  uint32_t payloadSumInSuperFrame = 0;
519  uint32_t payloadSumPerRcIndex[SatEnums::NUM_FIDS] = {};
520 
521  if (!info.second.empty())
522  {
523  NS_LOG_INFO("TBTP contains " << info.second.size()
524  << " timeslots for UT: " << m_nodeInfo->GetMacAddress());
525 
526  uint8_t frameId = info.first;
527 
528  // schedule time slots
529  for (SatTbtpMessage::DaTimeSlotConfContainer_t::iterator it = info.second.begin();
530  it != info.second.end();
531  it++)
532  {
533  Ptr<SatSuperframeConf> superframeConf =
535  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
536  Ptr<SatTimeSlotConf> timeSlotConf = *it;
537 
538  // Start time
539  Time slotDelay = startDelay + timeSlotConf->GetStartTime();
540  NS_LOG_INFO("Slot start delay: " << slotDelay.GetSeconds());
541 
542  // Duration
543  Ptr<SatWaveform> wf =
544  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
545  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
546 
547  bool drop = false;
548  if (timeSlotConf->GetSlotType() == SatTimeSlotConf::SLOT_TYPE_C)
549  {
550  wf = m_superframeSeq->GetWaveformConf()->GetWaveform(2);
551  duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
552  if (m_useLogon && m_rcstState.GetState() != SatUtMacState::RcstState_t::TDMA_SYNC &&
553  m_rcstState.GetState() != SatUtMacState::RcstState_t::READY_FOR_TDMA_SYNC)
554  {
555  drop = true;
556  }
557  }
558 
559  // Carrier
560  uint32_t carrierId =
561  m_superframeSeq->GetCarrierId(0, frameId, timeSlotConf->GetCarrierId());
562 
563  if (!drop)
564  {
565  // Schedule individual time slot
566  ScheduleDaTxOpportunity(slotDelay, duration, wf, timeSlotConf, carrierId);
567 
568  payloadSumInSuperFrame += wf->GetPayloadInBytes();
569  payloadSumPerRcIndex[timeSlotConf->GetRcIndex()] += wf->GetPayloadInBytes();
570  }
571  }
572  }
573 
574  // Assigned TBTP resources
575  m_tbtpResourcesTrace(payloadSumInSuperFrame);
576 
577  // Update the allocated TBTP resources for each RC index
578  for (uint32_t i = 0; i < SatEnums::NUM_FIDS; ++i)
579  {
580  m_assignedDaResourcesCallback(i, payloadSumPerRcIndex[i]);
581  }
582 }
583 
584 void
586  Time duration,
587  Ptr<SatWaveform> wf,
588  Ptr<SatTimeSlotConf> tsConf,
589  uint32_t carrierId)
590 {
591  NS_LOG_FUNCTION(this << transmitDelay.GetSeconds() << duration.GetSeconds()
592  << wf->GetPayloadInBytes() << (uint32_t)(tsConf->GetRcIndex())
593  << carrierId);
594  NS_LOG_INFO("After delay: " << transmitDelay.GetSeconds() << " duration: "
595  << duration.GetSeconds() << ", payload: " << wf->GetPayloadInBytes()
596  << ", rcIndex: " << (uint32_t)(tsConf->GetRcIndex())
597  << ", carrier: " << carrierId);
598 
599  transmitDelay = GetRealSendingTime(transmitDelay);
600 
601  if (transmitDelay >= Seconds(0))
602  {
603  Simulator::Schedule(transmitDelay,
605  this,
606  duration,
607  carrierId,
608  wf,
609  tsConf,
611  }
612 }
613 
614 void
615 SatUtMac::DoTransmit(Time duration,
616  uint32_t carrierId,
617  Ptr<SatWaveform> wf,
618  Ptr<SatTimeSlotConf> tsConf,
620 {
621  NS_LOG_FUNCTION(this << duration.GetSeconds() << wf->GetPayloadInBytes() << carrierId
622  << (uint32_t)(tsConf->GetRcIndex()));
623 
624  if (!m_txCheckCallback())
625  {
626  NS_LOG_INFO("Tx is unavailable");
628  return;
629  }
630 
631  if ((m_rcstState.GetState() != SatUtMacState::RcstState_t::TDMA_SYNC) &&
632  (tsConf->GetSlotType() != SatTimeSlotConf::SLOT_TYPE_C) && m_useLogon)
633  {
634  return;
635  }
636 
637  SatPhy::PacketContainer_t packets =
638  FetchPackets(wf->GetPayloadInBytes(), tsConf->GetSlotType(), tsConf->GetRcIndex(), policy);
639 
640  if (wf == m_superframeSeq->GetWaveformConf()->GetWaveform(2))
641  {
642  if (packets.size() == 0)
643  {
644  Ptr<Packet> p = Create<Packet>(wf->GetPayloadInBytes());
645 
646  // Mark the PDU with FULL_PDU tag
649  p->AddPacketTag(tag);
650 
651  // Add MAC tag to identify the packet in lower layers
652  SatMacTag mTag;
655  {
656  mTag.SetDestAddress(Mac48Address::ConvertFrom(m_satelliteAddress));
657  }
658  else
659  {
661  }
662  mTag.SetSourceAddress(m_nodeInfo->GetMacAddress());
663  p->AddPacketTag(mTag);
664 
665  // Add MAC tag to identify the packet in lower layers
666  SatAddressE2ETag addressE2ETag;
667  addressE2ETag.SetE2EDestAddress(m_gwAddress);
668  addressE2ETag.SetE2ESourceAddress(m_nodeInfo->GetMacAddress());
669  p->AddPacketTag(addressE2ETag);
670 
671  packets.push_back(p);
672  }
673  }
674 
675  NS_LOG_INFO("DA Tx opportunity for UT: "
676  << m_nodeInfo->GetMacAddress() << " duration: " << duration.GetSeconds()
677  << ", payload: " << wf->GetPayloadInBytes() << ", carrier: " << carrierId
678  << ", RC index: " << (uint32_t)(tsConf->GetRcIndex()));
679 
682  txInfo.modCod = wf->GetModCod();
683  txInfo.fecBlockSizeInBytes = wf->GetPayloadInBytes();
685  txInfo.waveformId = wf->GetWaveformId();
686 
687  if (txInfo.waveformId == 2 && tsConf->GetSlotType() != SatTimeSlotConf::SLOT_TYPE_C)
688  {
689  NS_FATAL_ERROR("WF02 should only be used for control bursts");
690  }
691 
692  TransmitPackets(packets, duration, carrierId, txInfo);
693 }
694 
695 void
697  Ptr<SatWaveform> waveform,
698  uint32_t carrierId,
699  uint8_t rcIndex,
701 {
702  NS_LOG_FUNCTION(this << duration.GetSeconds() << waveform->GetPayloadInBytes() << carrierId
703  << (uint32_t)(rcIndex));
704  NS_LOG_INFO("Tx opportunity for UT: "
705  << m_nodeInfo->GetMacAddress() << " duration: " << duration.GetSeconds()
706  << ", payload: " << waveform->GetPayloadInBytes() << ", carrier: " << carrierId
707  << ", RC index: " << (uint32_t)(rcIndex));
708 
710 
712  uint32_t payloadBytes = waveform->GetPayloadInBytes();
713 
715  payloadBytes -= m_randomAccess->GetSlottedAlohaSignalingOverheadInBytes();
716 
717  if (payloadBytes < 1)
718  {
719  NS_FATAL_ERROR(
720  "SatUtMac::DoSlottedAlohaTransmit - Not enough capacity in Slotted ALOHA payload");
721  }
722 
723  ExtractPacketsToSchedule(packets,
724  payloadBytes,
726  rcIndex,
727  policy,
728  true);
729 
730  if (!packets.empty())
731  {
732  NS_LOG_INFO("Number of packets sent in a slotted ALOHA slot: " << packets.size());
733 
734  for (SatPhy::PacketContainer_t::const_iterator it = packets.begin(); it != packets.end();
735  ++it)
736  {
737  // Add packet trace entry:
738  m_packetTrace(Simulator::Now(),
740  m_nodeInfo->GetNodeType(),
741  m_nodeInfo->GetNodeId(),
742  m_nodeInfo->GetMacAddress(),
746  }
747 
750  txInfo.modCod = waveform->GetModCod();
751  txInfo.fecBlockSizeInBytes = waveform->GetPayloadInBytes();
753  txInfo.waveformId = waveform->GetWaveformId();
754 
755  TransmitPackets(packets, duration, carrierId, txInfo);
756  }
757 }
758 
759 void
761  Ptr<SatWaveform> waveform,
762  uint32_t carrierId,
763  uint8_t rcIndex,
765 {
766  NS_LOG_FUNCTION(this << duration.GetSeconds() << waveform->GetPayloadInBytes() << carrierId
767  << (uint32_t)(rcIndex));
768  NS_LOG_INFO("SatUtMac::DoEssaTransmit - Tx opportunity for UT: "
769  << m_nodeInfo->GetMacAddress() << " at time: " << Simulator::Now().GetSeconds()
770  << " duration: " << duration.GetSeconds()
771  << ", payload: " << waveform->GetPayloadInBytes() << ", carrier: " << carrierId
772  << ", RC index: " << (uint32_t)(rcIndex));
773 
775  uint32_t payloadBytes = waveform->GetPayloadInBytes();
776 
779  m_utScheduler->DoScheduling(packets,
780  payloadBytes,
782  rcIndex,
783  policy);
784 
785  if (!packets.empty())
786  {
787  NS_LOG_INFO("Number of packets sent in a ESSA frame: " << packets.size());
788 
789  for (SatPhy::PacketContainer_t::const_iterator it = packets.begin(); it != packets.end();
790  ++it)
791  {
792  // Add packet trace entry:
793  m_packetTrace(Simulator::Now(),
795  m_nodeInfo->GetNodeType(),
796  m_nodeInfo->GetNodeId(),
797  m_nodeInfo->GetMacAddress(),
801  }
802 
806  txInfo.modCod = waveform->GetModCod();
807  txInfo.fecBlockSizeInBytes = waveform->GetPayloadInBytes();
809  txInfo.waveformId = waveform->GetWaveformId();
810  txInfo.crdsaUniquePacketId =
811  m_crdsaUniquePacketId; // reuse the crdsaUniquePacketId to identify ESSA frames
812 
813  TransmitPackets(packets, duration, carrierId, txInfo);
817  Now() + duration; // TODO: this doesn't take into account the guard bands !!
820  duration = GetRealSendingTime(duration);
821  if (duration >= Seconds(0))
822  {
823  Simulator::Schedule(duration,
825  this,
827  }
829  }
830  else
831  {
833  }
834 }
835 
837 SatUtMac::FetchPackets(uint32_t payloadBytes,
839  uint8_t rcIndex,
841 {
842  NS_LOG_FUNCTION(this << payloadBytes << (uint32_t)(rcIndex));
843 
850 
851  if (payloadBytes <= 0)
852  {
853  NS_FATAL_ERROR("SatUtMac::FetchPackets - unvalid slot payload: " << payloadBytes);
854  }
855 
856  ExtractPacketsToSchedule(packets, payloadBytes, type, rcIndex, policy, false);
857 
858  // A valid packet received
859  if (!packets.empty())
860  {
861  NS_LOG_INFO("Number of packets: " << packets.size());
862 
863  for (SatPhy::PacketContainer_t::const_iterator it = packets.begin(); it != packets.end();
864  ++it)
865  {
866  // Add packet trace entry:
867  m_packetTrace(Simulator::Now(),
869  m_nodeInfo->GetNodeType(),
870  m_nodeInfo->GetNodeId(),
871  m_nodeInfo->GetMacAddress(),
875  }
876  }
877 
878  NS_LOG_INFO("The Frame PDU holds " << packets.size() << " RLE PDUs");
879 
880  return packets;
881 }
882 
883 void
885  Time duration,
886  uint32_t carrierId,
888 {
889  NS_LOG_FUNCTION(this << packets.size() << duration.GetSeconds() << carrierId);
890 
891  if (m_rcstState.GetState() == SatUtMacState::RcstState_t::HOLD_STANDBY)
892  {
894  }
895 
896  if (m_rcstState.GetState() == SatUtMacState::RcstState_t::READY_FOR_TDMA_SYNC)
897  {
899  }
900 
901  // If there are packets to send
902  if (!packets.empty())
903  {
904  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << ", transmitting " << packets.size()
905  << " packets, duration: " << duration.GetSeconds()
906  << ", carrier: " << carrierId);
907 
908  // Decrease a guard time from time slot duration.
909  Time durationWithoutGuardPeriod(duration - m_guardTime);
910  NS_LOG_INFO("Duration: " << duration.GetSeconds() << " duration with guard period: "
911  << durationWithoutGuardPeriod.GetSeconds());
912  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " send packet");
913 
914  SendPacket(packets, carrierId, durationWithoutGuardPeriod, txInfo);
915  }
916 }
917 
918 void
920 {
921  NS_LOG_FUNCTION(this << event << (uint32_t)rcIndex);
922 
923  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " Queue: " << (uint32_t)rcIndex);
924 
925  // Check only the queue events from the control queue
926  if (rcIndex == SatEnums::CONTROL_FID)
927  {
928  if (event == SatQueue::FIRST_BUFFERED_PKT || event == SatQueue::BUFFERED_PKT)
929  {
930  NS_LOG_INFO("Buffered packet event received");
931 
932  if (m_randomAccess != NULL)
933  {
934  NS_LOG_INFO("Doing Slotted ALOHA");
935 
937  }
938  }
939  }
940 }
941 
942 void
944 {
945  NS_LOG_FUNCTION(this << event << (uint32_t)rcIndex);
946 
947  NS_LOG_INFO("SatUtMac::ReceiveQueueEventEssa - UT: " << m_nodeInfo->GetMacAddress()
948  << " time: " << Now().GetSeconds()
949  << " Queue: " << (uint32_t)rcIndex);
950 
951  // DoRandomAccess only if it is not scheduled yet
952  // NOTE: could use m_nextPacketTime to do the check
954  {
955  if (event == SatQueue::FIRST_BUFFERED_PKT || event == SatQueue::BUFFERED_PKT)
956  {
957  NS_LOG_INFO("SatUtMac::ReceiveQueueEventEssa - Buffered packet event received");
958 
959  if (m_randomAccess != NULL)
960  {
961  NS_LOG_INFO("SatUtMac::ReceiveQueueEventEssa - Doing ESSA");
962 
964  }
965  }
966  }
967 }
968 
969 void
970 SatUtMac::SendLogon(Ptr<Packet> packet)
971 {
973  packets.push_back(packet);
974 
975  Ptr<SatSuperframeConf> superframeConf =
977  uint8_t frameId = superframeConf->GetRaChannelFrameId(m_logonChannel);
978  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
979 
980  Ptr<SatTimeSlotConf> timeSlotConf = frameConf->GetTimeSlotConf(0);
981 
982  Ptr<SatWaveform> wf =
983  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
984  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
985 
986  uint32_t carrierId = m_superframeSeq->GetCarrierId(SatConstVariables::SUPERFRAME_SEQUENCE,
987  frameId,
988  timeSlotConf->GetCarrierId());
989 
992  txInfo.modCod = wf->GetModCod();
993  txInfo.sliceId = 0;
994  txInfo.fecBlockSizeInBytes = wf->GetPayloadInBytes();
996  txInfo.waveformId = wf->GetWaveformId();
997 
998  Time waitingTime = Seconds(m_waitingTimeLogonRng->GetValue(0.0,
999  pow(1 + m_sendLogonTries, 2) *
1000  m_windowInitLogon.GetSeconds()));
1001  m_sendLogonTries++;
1002  waitingTime = GetRealSendingTime(waitingTime);
1003  if (waitingTime >= Seconds(0))
1004  {
1005  Simulator::Schedule(waitingTime,
1007  this,
1008  packets,
1009  duration,
1010  carrierId,
1011  txInfo);
1012  }
1013 
1015  Simulator::Now() + m_maxWaitingTimeLogonResponse + waitingTime;
1016 }
1017 
1018 void
1019 SatUtMac::Receive(SatPhy::PacketContainer_t packets, Ptr<SatSignalParameters> /*rxParams*/)
1020 {
1021  NS_LOG_FUNCTION(this << packets.size());
1022 
1023  // Add packet trace entry:
1024  m_packetTrace(Simulator::Now(),
1026  m_nodeInfo->GetNodeType(),
1027  m_nodeInfo->GetNodeId(),
1028  m_nodeInfo->GetMacAddress(),
1031  SatUtils::GetPacketInfo(packets));
1032 
1033  // Invoke the `Rx` and `RxDelay` trace sources.
1034  RxTraces(packets);
1035 
1036  m_receptionDates.push(Simulator::Now());
1037  if (m_receptionDates.size() > 3)
1038  {
1039  m_receptionDates.pop();
1040  }
1041 
1042  for (SatPhy::PacketContainer_t::iterator i = packets.begin(); i != packets.end(); i++)
1043  {
1044  // Remove packet tag
1045  SatMacTag macTag;
1046  bool mSuccess = (*i)->PeekPacketTag(macTag);
1047  if (!mSuccess)
1048  {
1049  NS_FATAL_ERROR("MAC tag was not found from the packet!");
1050  }
1051 
1052  SatAddressE2ETag addressE2ETag;
1053  mSuccess = (*i)->PeekPacketTag(addressE2ETag);
1054  if (!mSuccess)
1055  {
1056  NS_FATAL_ERROR("SatAddressE2ETag was not found from the packet!");
1057  }
1058 
1059  NS_LOG_INFO("Packet from " << macTag.GetSourceAddress() << " to "
1060  << macTag.GetDestAddress());
1061  NS_LOG_INFO("Receiver " << m_nodeInfo->GetMacAddress());
1062 
1063  Mac48Address destAddress = macTag.GetDestAddress();
1064  if (destAddress == m_nodeInfo->GetMacAddress() || destAddress.IsBroadcast() ||
1065  destAddress.IsGroup())
1066  {
1067  // Remove control msg tag
1068  SatControlMsgTag ctrlTag;
1069  bool cSuccess = (*i)->PeekPacketTag(ctrlTag);
1070 
1071  if (cSuccess)
1072  {
1074 
1076  {
1078  }
1079  else
1080  {
1081  NS_FATAL_ERROR("A control message received with not valid msg type!");
1082  }
1083  }
1084  else if (destAddress.IsBroadcast())
1085  {
1086  // TODO: dummy frames and other broadcast needed to handle
1087  // dummy frames should ignored already in Phy layer
1088  }
1089  // Control msg tag not found, send the packet to higher layer
1090  else
1091  {
1092  // Pass the receiver address to LLC
1093  m_rxCallback(*i,
1094  addressE2ETag.GetE2ESourceAddress(),
1095  addressE2ETag.GetE2EDestAddress());
1096  }
1097  }
1098  }
1099 }
1100 
1101 void
1103 {
1104  NS_LOG_FUNCTION(this);
1105 
1106  // Remove the mac tag
1107  SatMacTag macTag;
1108  packet->PeekPacketTag(macTag);
1109 
1110  SatAddressE2ETag addressE2ETag;
1111  packet->PeekPacketTag(addressE2ETag);
1112 
1113  // Peek control msg tag
1114  SatControlMsgTag ctrlTag;
1115  bool cSuccess = packet->PeekPacketTag(ctrlTag);
1116 
1117  if (!cSuccess)
1118  {
1119  NS_FATAL_ERROR("SatControlMsgTag not found in the packet!");
1120  }
1121 
1122  switch (ctrlTag.GetMsgType())
1123  {
1125  uint32_t tbtpId = ctrlTag.GetMsgId();
1126 
1127  Ptr<SatTbtpMessage> tbtp = DynamicCast<SatTbtpMessage>(m_readCtrlCallback(tbtpId));
1128 
1134  if (tbtp == NULL)
1135  {
1136  NS_FATAL_ERROR("TBTP not found, check SatBeamHelper::CtrlMsgStoreTimeInFwdLink "
1137  "attribute is long enough!");
1138  }
1139 
1141  {
1143  m_firstTransmittableSuperframeId = tbtp->GetSuperframeCounter();
1144  }
1145  ScheduleTimeSlots(tbtp);
1146 
1147  packet->RemovePacketTag(macTag);
1148  packet->RemovePacketTag(addressE2ETag);
1149  packet->RemovePacketTag(ctrlTag);
1150 
1151  break;
1152  }
1154  // ARQ ACK messages are forwarded to LLC, since they may be fragmented
1155  m_rxCallback(packet, addressE2ETag.GetE2ESourceAddress(), macTag.GetDestAddress());
1156  break;
1157  }
1159  uint32_t raCtrlId = ctrlTag.GetMsgId();
1160  Ptr<SatRaMessage> raMsg = DynamicCast<SatRaMessage>(m_readCtrlCallback(raCtrlId));
1161 
1162  if (raMsg != NULL)
1163  {
1164  uint32_t allocationChannelId = raMsg->GetAllocationChannelId();
1165  uint16_t backoffProbability = raMsg->GetBackoffProbability();
1166  uint16_t backoffTime = raMsg->GetBackoffTime();
1167 
1168  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress()
1169  << " Updating RA backoff probability for AC: "
1170  << allocationChannelId << " to: " << backoffProbability);
1171 
1172  m_randomAccess->SetBackoffProbability(allocationChannelId, backoffProbability);
1173  m_randomAccess->SetBackoffTime(allocationChannelId, backoffTime);
1174 
1175  packet->RemovePacketTag(macTag);
1176  packet->RemovePacketTag(addressE2ETag);
1177  packet->RemovePacketTag(ctrlTag);
1178  }
1179  else
1180  {
1186  std::stringstream msg;
1187  msg << "Control message " << ctrlTag.GetMsgType()
1188  << " is not found from the FWD link control msg container!";
1189  msg << " at: " << Now().GetSeconds() << "s";
1190  Singleton<SatLog>::Get()->AddToLog(SatLog::LOG_WARNING, "", msg.str());
1191  }
1192  break;
1193  }
1195  uint32_t timuCtrlId = ctrlTag.GetMsgId();
1196  Ptr<SatTimuMessage> timuMsg = DynamicCast<SatTimuMessage>(m_readCtrlCallback(timuCtrlId));
1197 
1198  if (timuMsg != NULL)
1199  {
1200  uint32_t beamId = timuMsg->GetAllocatedBeamId();
1201  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " switching from beam " << m_beamId
1202  << " to beam " << beamId);
1203  if (m_beamId != beamId)
1204  {
1205  NS_LOG_INFO("Storing TIM-U information internally for later");
1206  m_timuInfo = Create<SatTimuInfo>(beamId, timuMsg->GetGwAddress());
1207  }
1208  }
1209  else
1210  {
1216  std::stringstream msg;
1217  msg << "Control message " << ctrlTag.GetMsgType()
1218  << " is not found from the FWD link control msg container!";
1219  msg << " at: " << Now().GetSeconds() << "s";
1220  Singleton<SatLog>::Get()->AddToLog(SatLog::LOG_WARNING, "", msg.str());
1221  }
1222  break;
1223  }
1225  uint32_t sliceCtrlId = ctrlTag.GetMsgId();
1226  Ptr<SatSliceSubscriptionMessage> sliceMsg =
1227  DynamicCast<SatSliceSubscriptionMessage>(m_readCtrlCallback(sliceCtrlId));
1228 
1229  if (sliceMsg != NULL)
1230  {
1231  if (m_nodeInfo->GetMacAddress() == sliceMsg->GetAddress())
1232  {
1233  m_sliceSubscriptionCallback(sliceMsg->GetSliceId());
1234  }
1235  }
1236  else
1237  {
1243  std::stringstream msg;
1244  msg << "Control message " << ctrlTag.GetMsgType()
1245  << " is not found from the FWD link control msg container!";
1246  msg << " at: " << Now().GetSeconds() << "s";
1247  Singleton<SatLog>::Get()->AddToLog(SatLog::LOG_WARNING, "", msg.str());
1248  }
1249  break;
1250  }
1252  uint32_t logonId = ctrlTag.GetMsgId();
1253  Ptr<SatLogonResponseMessage> logonMsg =
1254  DynamicCast<SatLogonResponseMessage>(m_readCtrlCallback(logonId));
1255 
1256  if (logonMsg != NULL)
1257  {
1258  m_raChannel = logonMsg->GetRaChannel();
1259  m_loggedOn = true;
1260  m_sendLogonTries = 0;
1261  m_rcstState.SetLogOffCallback(MakeCallback(&SatUtMac::LogOff, this));
1263  m_deltaNcr = Simulator::Now().GetMicroSeconds() * m_clockDrift / 1000000.0;
1264  }
1265  else
1266  {
1272  std::stringstream msg;
1273  msg << "Control message " << ctrlTag.GetMsgType()
1274  << " is not found from the FWD link control msg container!";
1275  msg << " at: " << Now().GetSeconds() << "s";
1276  Singleton<SatLog>::Get()->AddToLog(SatLog::LOG_WARNING, "", msg.str());
1277  }
1278  break;
1279  }
1281  uint32_t ncrCtrlId = ctrlTag.GetMsgId();
1282  Ptr<SatNcrMessage> ncrMsg = DynamicCast<SatNcrMessage>(m_readCtrlCallback(ncrCtrlId));
1283 
1284  m_lastNcrDateReceived = m_ncrV2 ? m_receptionDates.front() : Simulator::Now();
1285  m_ncr = ncrMsg->GetNcrDate();
1287 
1288  if (m_rcstState.GetState() == SatUtMacState::RcstState_t::NCR_RECOVERY)
1289  {
1291  {
1293  }
1294  else
1295  {
1297  }
1298  }
1299  break;
1300  }
1302  uint32_t cmtCtrlId = ctrlTag.GetMsgId();
1303  Ptr<SatCmtMessage> cmtMsg = DynamicCast<SatCmtMessage>(m_readCtrlCallback(cmtCtrlId));
1304  int16_t burstTimeCorrection = cmtMsg->GetBurstTimeCorrection();
1305  m_deltaNcr -= burstTimeCorrection;
1306  break;
1307  }
1309  uint32_t logoffCtrlId = ctrlTag.GetMsgId();
1310  Ptr<SatLogoffMessage> logoffMsg =
1311  DynamicCast<SatLogoffMessage>(m_readCtrlCallback(logoffCtrlId));
1312  LogOff();
1313  break;
1314  }
1315  default: {
1316  NS_FATAL_ERROR("SatUtMac received a non-supported control packet!");
1317  break;
1318  }
1319  }
1320 }
1321 
1322 void
1324 {
1325  NS_LOG_FUNCTION(this << randomAccessTriggerType);
1326 
1327  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress());
1328 
1329  if ((m_rcstState.GetState() != SatUtMacState::RcstState_t::TDMA_SYNC) && m_useLogon)
1330  {
1331  return;
1332  }
1333 
1336  m_isRandomAccessScheduled = false;
1337 
1339 
1341  uint32_t allocationChannel = GetNextRandomAccessAllocationChannel();
1342 
1343  if (m_useLogon && allocationChannel == m_logonChannel)
1344  {
1345  NS_LOG_INFO("Logon channel cannot be used for RA transmition");
1346  return;
1347  }
1348 
1350  txOpportunities = m_randomAccess->DoRandomAccess(allocationChannel, randomAccessTriggerType);
1351 
1354  {
1355  Time txOpportunity = GetRealSendingTime(
1356  Time::FromInteger(txOpportunities.slottedAlohaTxOpportunity, Time::MS));
1357 
1358  NS_LOG_INFO("Processing Slotted ALOHA results, Tx evaluation @: "
1359  << (Now() + txOpportunity).GetSeconds() << " seconds");
1360 
1362  if (txOpportunity >= Seconds(0))
1363  {
1364  Simulator::Schedule(txOpportunity,
1366  this,
1367  allocationChannel);
1368  }
1369  }
1371  else if (txOpportunities.txOpportunityType == SatEnums::RA_TX_OPPORTUNITY_CRDSA)
1372  {
1373  NS_LOG_INFO("Processing CRDSA results");
1374 
1376  ScheduleCrdsaTransmission(allocationChannel, txOpportunities);
1377  }
1379  else if (txOpportunities.txOpportunityType == SatEnums::RA_TX_OPPORTUNITY_ESSA)
1380  {
1381  NS_LOG_INFO("SatUtMac::DoRandomAccess - Processing ESSA results");
1386  Time txOpportunity = GetRealSendingTime(
1387  Time::FromInteger(txOpportunities.slottedAlohaTxOpportunity, Time::MS));
1388 
1390  if (txOpportunity >= Seconds(0))
1391  {
1392  Simulator::Schedule(txOpportunity,
1394  this,
1395  allocationChannel);
1396  }
1397  }
1398 }
1399 
1400 uint32_t
1402 {
1403  NS_LOG_FUNCTION(this);
1404 
1405  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " has allocation channel " << m_raChannel);
1406 
1408  return m_raChannel;
1409 }
1410 
1411 void
1413 {
1414  NS_LOG_FUNCTION(this << allocationChannel);
1415 
1416  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " AC: " << allocationChannel);
1417 
1421  if (!m_tbtpContainer->HasScheduledTimeSlots())
1422  {
1423  NS_LOG_INFO("No known DAMA, selecting a slot for Slotted ALOHA");
1424 
1425  Ptr<SatSuperframeConf> superframeConf =
1427  uint8_t frameId = superframeConf->GetRaChannelFrameId(allocationChannel);
1428  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
1429  uint32_t timeSlotCount = frameConf->GetTimeSlotCount();
1430 
1431  std::pair<bool, uint32_t> result = std::make_pair(false, 0);
1432  Time superframeStartTime =
1434 
1435  if (Now() < superframeStartTime)
1436  {
1437  NS_FATAL_ERROR("SatUtMac::ScheduleSlottedAlohaTransmission - Invalid SF start time");
1438  }
1439 
1441 
1442  NS_LOG_INFO("Searching for next available slot");
1443 
1446  while (!result.first)
1447  {
1448  NS_LOG_INFO("SuperFrameId: " << superFrameId << ", superframeStartTime: "
1449  << superframeStartTime.GetSeconds());
1450 
1451  result = SearchFrameForAvailableSlot(superframeStartTime,
1452  frameConf,
1453  timeSlotCount,
1454  superFrameId,
1455  allocationChannel);
1456 
1457  if (!result.first)
1458  {
1459  NS_LOG_INFO("Increasing frame offset!");
1460  superFrameId++;
1461  superframeStartTime += frameConf->GetDuration();
1462  }
1463  }
1464 
1466  Ptr<SatTimeSlotConf> timeSlotConf = frameConf->GetTimeSlotConf(result.second);
1467 
1469  Time slotStartTime = superframeStartTime + timeSlotConf->GetStartTime();
1470  Time offset = slotStartTime - Now();
1471 
1472  if (offset.IsStrictlyNegative())
1473  {
1474  NS_FATAL_ERROR("SatUtMac::ScheduleSlottedAlohaTransmission - Invalid transmit time: "
1475  << offset.GetSeconds());
1476  }
1477 
1479  Ptr<SatWaveform> wf =
1480  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
1481  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
1482 
1484  uint32_t carrierId =
1485  m_superframeSeq->GetCarrierId(0, frameId, timeSlotConf->GetCarrierId());
1486 
1487  NS_LOG_INFO("Starting to schedule, SF ID: "
1488  << superFrameId << " slot: " << result.second
1489  << " SF start: " << superframeStartTime.GetSeconds()
1490  << " Tx start: " << (Now() + offset).GetSeconds()
1491  << " duration: " << duration.GetSeconds() << " carrier ID: " << carrierId
1492  << " payload in bytes: " << wf->GetPayloadInBytes());
1493 
1495  offset = GetRealSendingTime(offset);
1496  if (offset >= Seconds(0))
1497  {
1498  Simulator::Schedule(offset,
1500  this,
1501  duration,
1502  wf,
1503  carrierId,
1504  uint8_t(SatEnums::CONTROL_FID),
1506  }
1507  }
1508  else
1509  {
1510  NS_LOG_INFO("UT has known DAMA, aborting Slotted ALOHA");
1511  }
1512 }
1513 
1514 std::pair<bool, uint32_t>
1515 SatUtMac::SearchFrameForAvailableSlot(Time superframeStartTime,
1516  Ptr<SatFrameConf> frameConf,
1517  uint32_t timeSlotCount,
1518  uint32_t superFrameId,
1519  uint32_t allocationChannel)
1520 {
1521  NS_LOG_FUNCTION(this << superframeStartTime << timeSlotCount << superFrameId
1522  << allocationChannel);
1523 
1524  Time opportunityOffset = Now() - superframeStartTime;
1525 
1526  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress()
1527  << " offset: " << opportunityOffset.GetSeconds());
1528 
1531  if (opportunityOffset.IsStrictlyNegative())
1532  {
1533  opportunityOffset = Seconds(0);
1534  }
1535 
1536  return FindNextAvailableRandomAccessSlot(opportunityOffset,
1537  frameConf,
1538  timeSlotCount,
1539  superFrameId,
1540  allocationChannel);
1541 }
1542 
1543 std::pair<bool, uint32_t>
1545  Ptr<SatFrameConf> frameConf,
1546  uint32_t timeSlotCount,
1547  uint32_t superFrameId,
1548  uint32_t allocationChannel)
1549 {
1550  NS_LOG_FUNCTION(this << opportunityOffset << timeSlotCount << superFrameId
1551  << allocationChannel);
1552 
1553  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress());
1554 
1555  Ptr<SatTimeSlotConf> slotConf;
1556  uint32_t slotId;
1557  bool availableSlotFound = false;
1558 
1560  for (slotId = 0; slotId < timeSlotCount; slotId++)
1561  {
1562  slotConf = frameConf->GetTimeSlotConf(slotId);
1563 
1564  // NS_LOG_INFO ("Slot: " << slotId <<
1565  // " slot offset: " << slotConf->GetStartTime.GetSeconds () <<
1566  // " opportunity offset: " << opportunityOffset.GetSeconds ());
1567 
1570  if (slotConf->GetStartTime() >= opportunityOffset)
1571  {
1573  if (UpdateUsedRandomAccessSlots(superFrameId, allocationChannel, slotId))
1574  {
1575  availableSlotFound = true;
1576  break;
1577  }
1578  }
1579  }
1580 
1581  NS_LOG_INFO("Success: " << availableSlotFound << " SF: " << superFrameId << " AC: "
1582  << allocationChannel << " slot: " << slotId << "/" << timeSlotCount);
1583 
1584  return std::make_pair(availableSlotFound, slotId);
1585 }
1586 
1587 void
1588 SatUtMac::ScheduleEssaTransmission(uint32_t allocationChannel)
1589 {
1590  // TODO: do we really need the allocationChannel ???
1591  NS_LOG_FUNCTION(this << allocationChannel);
1592 
1593  NS_LOG_INFO("SatUtMac::ScheduleEssaTransmission - UT: " << m_nodeInfo->GetMacAddress()
1594  << " time: " << Now().GetSeconds()
1595  << " AC: " << allocationChannel);
1596 
1598  Time offset = m_nextPacketTime - Now();
1599 
1600  if (offset.IsStrictlyNegative())
1601  {
1603  offset = Seconds(0);
1604  }
1605 
1607  Ptr<SatSuperframeConf> superframeConf =
1609  uint8_t frameId = superframeConf->GetRaChannelFrameId(allocationChannel);
1610  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
1611  Ptr<SatTimeSlotConf> timeSlotConf = frameConf->GetTimeSlotConf(0); // only one timeslot on ESSA
1612 
1613  Ptr<SatWaveform> wf =
1614  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
1615  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
1616 
1617  NS_LOG_INFO("SatUtMac::ScheduleEssaTransmission - Starting to schedule @ "
1618  << Now().GetSeconds() << " Tx start: " << (Now() + offset).GetSeconds()
1619  << " duration: " << duration.GetSeconds()
1620  << " payload in bytes: " << wf->GetPayloadInBytes());
1621 
1623  uint32_t carrierId = 0; // TODO: for now we use 0 as we have a single carrier
1624 
1626  offset = GetRealSendingTime(offset);
1627  if (offset >= Seconds(0))
1628  {
1629  Simulator::Schedule(offset,
1631  this,
1632  duration,
1633  wf,
1634  carrierId,
1635  uint8_t(SatEnums::CONTROL_FID),
1637  }
1638 }
1639 
1640 void
1641 SatUtMac::ScheduleCrdsaTransmission(uint32_t allocationChannel,
1643 {
1644  NS_LOG_FUNCTION(this << allocationChannel);
1645 
1646  // get current superframe ID
1647  Time now = Simulator::Now();
1650  NS_LOG_INFO("Checking for CRDSA transmission at "
1651  << now.GetMilliSeconds() - superFrameStart.GetMilliSeconds()
1652  << " milliseconds into superframe " << superFrameId);
1653 
1654  // TODO: check we didn't already scheduled packets for this superframe
1655  // (because we are moving so fast, for instance, that we are now at the end of the
1656  // window for this "past" superframe instead of the beginning of the next one)
1657 
1658  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " AC: " << allocationChannel
1659  << ", SF: " << superFrameId << ", num of opportunities: "
1660  << txOpportunities.crdsaTxOpportunities.size());
1661 
1662  std::map<uint32_t, std::set<uint32_t>>::iterator iter;
1663 
1665  for (iter = txOpportunities.crdsaTxOpportunities.begin();
1666  iter != txOpportunities.crdsaTxOpportunities.end();
1667  iter++)
1668  {
1669  std::set<uint32_t>::iterator iterSet;
1670 
1672  for (iterSet = iter->second.begin(); iterSet != iter->second.end(); iterSet++)
1673  {
1675  if (!UpdateUsedRandomAccessSlots(superFrameId, allocationChannel, *iterSet))
1676  {
1679  NS_FATAL_ERROR(
1680  "SatUtMac::ScheduleCrdsaTransmission - Slot unavailable: " << *iterSet);
1681  }
1682  }
1683 
1685  NS_LOG_INFO("Creating replicas for packet " << (uint32_t)m_crdsaUniquePacketId);
1686  CreateCrdsaPacketInstances(allocationChannel, iter->second);
1687  }
1688 }
1689 
1690 void
1691 SatUtMac::CreateCrdsaPacketInstances(uint32_t allocationChannel, std::set<uint32_t> slots)
1692 {
1693  NS_LOG_FUNCTION(this << allocationChannel);
1694 
1695  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " AC: " << allocationChannel);
1696 
1697  Ptr<SatSuperframeConf> superframeConf =
1699  uint8_t frameId = superframeConf->GetRaChannelFrameId(allocationChannel);
1700  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
1701 
1704  Time superframeStartTime = Now();
1705 
1707  uint32_t payloadBytes = superframeConf->GetRaChannelTimeSlotPayloadInBytes(allocationChannel);
1708 
1710  payloadBytes -= m_randomAccess->GetCrdsaSignalingOverheadInBytes();
1711 
1712  if (payloadBytes < 1)
1713  {
1714  NS_FATAL_ERROR(
1715  "SatUtMac::CreateCrdsaPacketInstances - Not enough capacity in CRDSA payload");
1716  }
1717 
1722  {
1723  policy = SatUtScheduler::STRICT;
1724  }
1725  else
1726  {
1727  policy = SatUtScheduler::LOOSE;
1728  }
1729 
1733  payloadBytes,
1735  uint8_t(SatEnums::CONTROL_FID),
1736  policy,
1737  true);
1738 
1739  NS_LOG_INFO("Processing the packet container, fragments: " << uniq.size());
1740 
1741  if (!uniq.empty())
1742  {
1743  std::vector<std::pair<uint16_t, SatPhy::PacketContainer_t>> replicas;
1744  std::map<uint16_t, SatCrdsaReplicaTag> tags;
1745  std::set<uint32_t>::iterator iterSet;
1746 
1747  NS_LOG_INFO("Creating replicas for a packet");
1748 
1750  for (iterSet = slots.begin(); iterSet != slots.end(); iterSet++)
1751  {
1753  SatPhy::PacketContainer_t::const_iterator it = uniq.begin();
1754 
1755  for (; it != uniq.end(); ++it)
1756  {
1757  rep.push_back((*it)->Copy());
1758  NS_LOG_INFO(
1759  "Replica in slot: "
1760  << (*iterSet) << ", original (HL packet) fragment UID: " << (*it)->GetUid()
1761  << ", copied replica fragment (HL packet) UID: " << rep.back()->GetUid());
1762  }
1763 
1764  NS_LOG_INFO("One replica created");
1765 
1766  replicas.push_back(std::make_pair(*iterSet, rep));
1767  }
1768 
1769  NS_LOG_INFO("Creating replica tags");
1770 
1772  for (uint32_t i = 0; i < replicas.size(); i++)
1773  {
1774  SatCrdsaReplicaTag replicaTag;
1775 
1776  replicaTag.AddSlotId(replicas[i].first);
1777 
1778  NS_LOG_INFO("Own packet tag: " << replicas[i].first);
1779 
1780  for (uint32_t j = 0; j < replicas.size(); j++)
1781  {
1782  if (i != j)
1783  {
1784  replicaTag.AddSlotId(replicas[j].first);
1785 
1786  NS_LOG_INFO("Other packet tag: " << replicas[j].first);
1787  }
1788  }
1789  tags.insert(std::make_pair(replicas[i].first, replicaTag));
1790  }
1791 
1792  NS_LOG_INFO("Scheduling replicas");
1793 
1795  for (uint32_t i = 0; i < replicas.size(); i++)
1796  {
1797  for (uint32_t j = 0; j < replicas[i].second.size(); j++)
1798  {
1799  NS_LOG_INFO("Replica: " << i << ", fragment: " << j
1800  << ", key: " << replicas[i].first << ", tag: "
1801  << tags.at(replicas[i].first).GetSlotIds().at(0)
1802  << ", fragment (HL packet) UID: "
1803  << replicas[i].second.at(j)->GetUid());
1804 
1806  replicas[i].second.at(j)->AddPacketTag(tags.at(replicas[i].first));
1807  }
1808 
1810  Ptr<SatTimeSlotConf> timeSlotConf = frameConf->GetTimeSlotConf(replicas[i].first);
1811 
1813  Time slotDelay = superframeStartTime + timeSlotConf->GetStartTime();
1814  Time offset = slotDelay - Now();
1815 
1816  if (offset.IsStrictlyNegative())
1817  {
1818  NS_FATAL_ERROR("SatUtMac::CreateCrdsaPacketInstances - Invalid transmit time: "
1819  << offset.GetSeconds());
1820  }
1821 
1823  Ptr<SatWaveform> wf =
1824  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
1825  Time duration = wf->GetBurstDuration(frameConf->GetBtuConf()->GetSymbolRateInBauds());
1826 
1828  uint32_t carrierId =
1830  frameId,
1831  timeSlotConf->GetCarrierId());
1832 
1836  txInfo.modCod = wf->GetModCod();
1837  txInfo.sliceId = 0;
1838  txInfo.fecBlockSizeInBytes = wf->GetPayloadInBytes();
1840  txInfo.waveformId = wf->GetWaveformId();
1842 
1844  offset = GetRealSendingTime(offset);
1845  if (offset >= Seconds(0))
1846  {
1847  Simulator::Schedule(offset,
1849  this,
1850  replicas[i].second,
1851  duration,
1852  carrierId,
1853  txInfo);
1854  }
1855  NS_LOG_INFO("Scheduled a replica in slot " << replicas[i].first << " with offset "
1856  << offset.GetSeconds());
1857  }
1858  replicas.clear();
1859  tags.clear();
1860 
1862  }
1863 }
1864 
1865 bool
1867  uint32_t allocationChannelId,
1868  uint32_t slotId)
1869 {
1870  NS_LOG_FUNCTION(this << superFrameId << allocationChannelId << slotId);
1871 
1872  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " SF: " << superFrameId
1873  << " AC: " << allocationChannelId << " slot: " << slotId);
1874 
1875  std::map<std::pair<uint32_t, uint32_t>, std::set<uint32_t>>::iterator iter;
1876  bool isSlotFree = false;
1877 
1879  RemovePastRandomAccessSlots(superFrameId);
1880 
1881  std::pair<uint32_t, uint32_t> key = std::make_pair(superFrameId, allocationChannelId);
1882 
1883  iter = m_usedRandomAccessSlots.find(key);
1884 
1885  if (iter == m_usedRandomAccessSlots.end())
1886  {
1887  std::set<uint32_t> txOpportunities{{slotId}};
1888  std::pair<std::map<std::pair<uint32_t, uint32_t>, std::set<uint32_t>>::iterator, bool>
1889  result;
1890  result = m_usedRandomAccessSlots.insert(std::make_pair(key, txOpportunities));
1891 
1892  if (result.second)
1893  {
1894  isSlotFree = true;
1895  NS_LOG_INFO("No saved SF, slot " << slotId << " saved in SF " << superFrameId);
1896  }
1897  else
1898  {
1899  NS_LOG_WARN("No saved SF but unable to create one");
1900  }
1901  }
1902  else
1903  {
1904  std::pair<std::set<uint32_t>::iterator, bool> result;
1905  result = iter->second.insert(slotId);
1906 
1907  if (result.second)
1908  {
1909  isSlotFree = true;
1910  NS_LOG_INFO("Saved SF exist, slot " << slotId << " saved in SF " << superFrameId);
1911  }
1912  else
1913  {
1914  NS_LOG_WARN("Saved SF exist but unable to add slot " << slotId);
1915  }
1916  }
1917  return isSlotFree;
1918 }
1919 
1920 void
1922 {
1923  NS_LOG_FUNCTION(this << superFrameId);
1924 
1925  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress() << " SF: " << superFrameId);
1926 
1927  std::map<std::pair<uint32_t, uint32_t>, std::set<uint32_t>>::iterator iter;
1928 
1929  for (iter = m_usedRandomAccessSlots.begin(); iter != m_usedRandomAccessSlots.end();)
1930  {
1931  if (iter->first.first < superFrameId)
1932  {
1933  iter = m_usedRandomAccessSlots.erase(iter);
1934  }
1935  else
1936  {
1937  ++iter;
1938  }
1939  }
1940 }
1941 
1942 void
1944 {
1945  NS_LOG_FUNCTION(this);
1946 
1947  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress());
1948  std::cout << "UT: " << m_nodeInfo->GetMacAddress() << std::endl;
1949 
1950  for (auto& iter : m_usedRandomAccessSlots)
1951  {
1952  for (auto& slot : iter.second)
1953  {
1954  std::cout << "SF: " << iter.first.first << " AC: " << iter.first.second
1955  << " slot: " << slot << std::endl;
1956  }
1957  }
1958 }
1959 
1960 void
1962 {
1963  NS_LOG_FUNCTION(this);
1964 
1965  NS_LOG_INFO("UT: " << m_nodeInfo->GetMacAddress());
1966 
1967  if (m_timuInfo != NULL)
1968  {
1969  NS_LOG_INFO("Applying TIM-U parameters received during the previous frame");
1970 
1971  m_beamId = m_timuInfo->GetBeamId();
1972  Address gwAddress = m_timuInfo->GetGwAddress();
1973  Mac48Address gwAddress48 = Mac48Address::ConvertFrom(gwAddress);
1974  if (gwAddress48 != m_gwAddress)
1975  {
1976  SetGwAddress(gwAddress48);
1977  m_routingUpdateCallback(m_nodeInfo->GetMacAddress(), gwAddress);
1978  }
1980 
1981  m_tbtpContainer->Clear();
1983  m_timuInfo = NULL;
1984  }
1985  else if (m_txCheckCallback())
1986  {
1987  NS_LOG_INFO("Tx is permitted");
1988 
1989  if (m_rcstState.GetState() == SatUtMacState::RcstState_t::HOLD_STANDBY)
1990  {
1992  }
1993 
1994  if (m_loggedOn && !m_beamCheckerCallback.IsNull())
1995  {
1996  NS_LOG_INFO("UT checking for beam handover recommendation");
1998  {
2000  {
2003  }
2005  {
2007  }
2009  {
2011  LogOff();
2012 
2014 
2015  Address gwAddress = m_beamScheculerCallback(m_satId, m_beamId)->GetGwAddress();
2016  Mac48Address gwAddress48 = Mac48Address::ConvertFrom(gwAddress);
2017  if (gwAddress48 != m_gwAddress)
2018  {
2019  SetGwAddress(gwAddress48);
2020  m_updateGwAddressCallback(gwAddress48);
2021  m_routingUpdateCallback(m_nodeInfo->GetMacAddress(), gwAddress);
2022  }
2024 
2025  m_tbtpContainer->Clear();
2027  m_nextLogonTransmissionPossible = Simulator::Now();
2028  }
2029  }
2030  }
2031 
2032  if (m_randomAccess != NULL)
2033  {
2034  if (m_loggedOn)
2035  {
2036  // reset packet ID counter for this frame
2038 
2039  // execute CRDSA trigger
2041  }
2042  else if (m_useLogon)
2043  {
2045  if (Simulator::Now() > m_nextLogonTransmissionPossible)
2046  {
2047  // Do Logon
2049  }
2050  }
2051  }
2052  }
2053  else
2054  {
2055  NS_LOG_INFO("Tx is disabled");
2057  }
2058 
2060  NS_ASSERT_MSG(Now() < nextSuperFrameTxTime,
2061  "Scheduling next superframe start time to the past!");
2062 
2063  Time schedulingDelay = nextSuperFrameTxTime - Now();
2064  Time realDelay = GetRealSendingTime(schedulingDelay);
2065  if (realDelay == Seconds(0))
2066  {
2067  schedulingDelay += m_superframeSeq->GetDuration(SatConstVariables::SUPERFRAME_SEQUENCE);
2068  }
2069  Simulator::Schedule(GetRealSendingTime(schedulingDelay), &SatUtMac::DoFrameStart, this);
2070 }
2071 
2072 Time
2074 {
2075  if (m_deltaNcr == 0) // For some reason returning t-0 is different than returning t...
2076  {
2077  return t;
2078  }
2079 
2080  uint32_t driftTicks = (t + Simulator::Now()).GetMicroSeconds() * m_clockDrift / 1000000;
2081  int32_t deltaTicks = m_deltaNcr - driftTicks;
2082  Time deltaTime = NanoSeconds(deltaTicks * 1000 / 27.0);
2083 
2084  return t - deltaTime;
2085 }
2086 
2087 SatUtMac::SatTimuInfo::SatTimuInfo(uint32_t beamId, Address address)
2088  : m_beamId(beamId),
2089  m_gwAddress(address)
2090 {
2091  NS_LOG_FUNCTION(this << beamId << address);
2092 }
2093 
2094 uint32_t
2096 {
2097  NS_LOG_FUNCTION(this);
2098  return m_beamId;
2099 }
2100 
2101 Address
2103 {
2104  NS_LOG_FUNCTION(this);
2105  return m_gwAddress;
2106 }
2107 
2110 {
2111  NS_LOG_FUNCTION(this);
2112  return m_rcstState.GetState();
2113 }
2114 
2115 void
2117  uint32_t payloadBytes,
2119  uint8_t rcIndex,
2121  bool randomAccessChannel)
2122 {
2123  NS_LOG_INFO(this << payloadBytes << type << rcIndex << policy << randomAccessChannel);
2124 
2126  if ((m_handoverState == NO_HANDOVER &&
2127  (randomAccessChannel || m_firstTransmittableSuperframeId <= superFrameId)) ||
2128  (randomAccessChannel && m_handoverState != HANDOVER_RECOMMENDATION_SENT))
2129  {
2130  NS_LOG_INFO("Regular scheduling");
2131  m_utScheduler->DoScheduling(packets, payloadBytes, type, rcIndex, policy);
2132  }
2133  else
2134  {
2135  NS_LOG_INFO("Handover recommendation sent, force control packets only");
2136  m_utScheduler->DoScheduling(packets,
2137  payloadBytes,
2141 
2142  // Remove every control packets except handover requests
2143  SatPhy::PacketContainer_t::iterator it = packets.begin();
2144  while (it != packets.end())
2145  {
2146  SatControlMsgTag ctrlTag;
2147  bool success = (*it)->PeekPacketTag(ctrlTag);
2148 
2149  if (success && ctrlTag.GetMsgType() == SatControlMsgTag::SAT_HR_CTRL_MSG)
2150  {
2151  ++it;
2152  }
2153  else
2154  {
2155  it = packets.erase(it);
2156  }
2157  }
2158  }
2159 }
2160 
2161 } // 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.
RegenerationMode_t
The regeneration mode used in satellites.
RandomAccessTriggerType_t
The defined random access trigger types.
@ LOG_WARNING
LOG_WARNING.
Definition: satellite-log.h:64
Base MAC class for SatNetDevices.
Definition: satellite-mac.h:52
void RxTraces(SatPhy::PacketContainer_t packets)
Invoke the Rx trace source for each received packet.
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.
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.
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:78
@ 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, Address address)
void SetRandomAccess(Ptr< SatRandomAccess > randomAccess)
Set the random access module.
void SetBeamScheculerCallback(SatUtMac::BeamScheculerCallback cb)
Set the beam scheduler callback.
void SetAskedBeamCallback(SatUtMac::AskedBeamCallback cb)
Method to get the best beam when performing handover.
Callback< void, uint32_t > HandoverCallback
Callback to reconfigure physical layer during handover.
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)
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.
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.
SatUtMac::BeamScheculerCallback m_beamScheculerCallback
Callback to get the SatBeamScheduler linked to a beam ID.
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.
Callback< uint32_t > AskedBeamCallback
Callback to ask for the best beam ID during handover.
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.
SatUtMac::BeamCheckerCallback m_beamCheckerCallback
Beam checker and handover recommendation sending callback.
Callback< bool, uint32_t, uint32_t > BeamCheckerCallback
Callback to check whether the current beam is still the best one to use for sending data; and sending...
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)
void SetBeamCheckerCallback(SatUtMac::BeamCheckerCallback cb)
Method to set the beam checker callback.
Ptr< SatRandomAccess > m_randomAccess
RA main module.
bool m_isRandomAccessScheduled
Flag that indicates if a method DoRandomAccess is scheduled for asynchronous access.
Callback< Ptr< SatBeamScheduler >, uint32_t, uint32_t > BeamScheculerCallback
Callback to get the SatBeamScheduler from the beam ID for handover.
TimingAdvanceCallback m_timingAdvanceCb
Callback for getting the timing advance information.
uint32_t m_satId
ID of sat for UT.
SatUtMac::AskedBeamCallback m_askedBeamCallback
Beam checker and handover recommendation sending callback.
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 DoRandomAccess(SatEnums::RandomAccessTriggerType_t randomAccessTriggerType)
Do random access evaluation for Tx opportunities.
Callback< void, uint8_t > SliceSubscriptionCallback
Callback to check if TX is operational.
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.