satellite-phy-rx-carrier-per-slot.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: Jani Puttonen <jani.puttonen@magister.fi>
20  * Author: Mathias Ettinger <mettinger@toulouse.viveris.fr>
21  */
22 
24 
26 
27 #include <ns3/address.h>
28 #include <ns3/boolean.h>
29 #include <ns3/log.h>
30 #include <ns3/simulator.h>
31 
32 #include <algorithm>
33 #include <deque>
34 #include <limits>
35 #include <ostream>
36 #include <utility>
37 
38 NS_LOG_COMPONENT_DEFINE("SatPhyRxCarrierPerSlot");
39 
40 namespace ns3
41 {
42 
43 NS_OBJECT_ENSURE_REGISTERED(SatPhyRxCarrierPerSlot);
44 
46  Ptr<SatPhyRxCarrierConf> carrierConf,
47  Ptr<SatWaveformConf> waveformConf,
48  bool randomAccessEnabled)
49  : SatPhyRxCarrier(carrierId, carrierConf, waveformConf, randomAccessEnabled),
50  m_randomAccessBitsInFrame(0),
51  m_randomAccessAllocationChannelId(0),
52  m_randomAccessCollisionModel(SatPhyRxCarrierConf::RA_COLLISION_NOT_DEFINED),
53  m_randomAccessConstantErrorRate(0.0),
54  m_randomAccessAverageNormalizedOfferedLoadMeasurementWindowSize(0),
55  m_enableRandomAccessDynamicLoadControl(false),
56  m_disableErrorHighTransmissionTime(false)
57 {
58  if (randomAccessEnabled)
59  {
60  m_randomAccessCollisionModel = carrierConf->GetRandomAccessCollisionModel();
61  m_randomAccessConstantErrorRate = carrierConf->GetRandomAccessConstantErrorRate();
63  carrierConf->GetRandomAccessAverageNormalizedOfferedLoadMeasurementWindowSize();
65  carrierConf->IsRandomAccessDynamicLoadControlEnabled();
66 
67  NS_LOG_INFO("RA interference model: "
68  << carrierConf->GetInterferenceModel(true)
69  << ", RA collision model: " << m_randomAccessCollisionModel
70  << ", RA avg. normalized offered load measurement window size: "
72  }
73 }
74 
76 {
77  NS_LOG_FUNCTION(this);
78 }
79 
80 void
82 {
83 }
84 
85 TypeId
87 {
88  static TypeId tid =
89  TypeId("ns3::SatPhyRxCarrierPerSlot")
90  .SetParent<SatPhyRxCarrier>()
91  .AddAttribute(
92  "DisableErrorHighTransmissionTime",
93  "Disable fatal error when transmission time is higher than propagation time, but "
94  "computations are less precise.",
95  BooleanValue(false),
97  MakeBooleanChecker())
98  .AddTraceSource(
99  "SlottedAlohaRxCollision",
100  "Received a packet burst through Random Access Slotted ALOHA",
102  "ns3::SatPhyRxCarrierPacketProbe::RxStatusCallback")
103  .AddTraceSource(
104  "SlottedAlohaRxError",
105  "Received a packet burst through Random Access Slotted ALOHA",
106  MakeTraceSourceAccessor(&SatPhyRxCarrierPerSlot::m_slottedAlohaRxErrorTrace),
107  "ns3::SatPhyRxCarrierPacketProbe::RxStatusCallback");
108  return tid;
109 }
110 
111 void
113 {
114  NS_LOG_FUNCTION(this);
115 
118 }
119 
120 Ptr<SatInterference::InterferenceChangeEvent>
121 SatPhyRxCarrierPerSlot::CreateInterference(Ptr<SatSignalParameters> rxParams, Address senderAddress)
122 {
123  NS_LOG_FUNCTION(this << rxParams << senderAddress);
124 
125  // Case satellite regenerative
127  {
128  return GetInterferenceModel()->Add(rxParams->m_duration,
129  rxParams->m_rxPower_W,
130  GetOwnAddress());
131  }
132 
134  if (ct == SatEnums::RETURN_FEEDER_CH)
135  {
136  // In feeder downlink the interference by UTs in the same
137  // beam (intra-beam interference e.g. due to random access) SHOULD NOT be tracked.
138  // Intra-beam interference is already taken into account at the satellite. Thus,
139  // here we pass intra-beam transmissions with zero interference power to the
140  // interference model.
141  // Rx power in the rxParams is the received power of only one of the interfering
142  // signals of the wanted signal. In reality, we are receiving the same signal
143  // through all the co-channel transponders of the satellite, where the rxPower
144  // is the C and all the other components are considered as interference I.
145  // This can be compensated with the following equation:
146  // rxPower = rxParams->m_rxPower_W * (1 + 1/rxParams->m_sinr);
147  // See more from satellite module documentation.
148 
149  double rxPower(0.0);
150 
151  if (rxParams->m_beamId != GetBeamId())
152  {
153  if (!rxParams->HasSinrComputed())
154  {
156  {
157  NS_LOG_WARN("SatPhyRx::StartRx - too long transmission time: packet started to "
158  "be received in a ground entity while not being fully received on "
159  "the satellite: interferences could not be properly computed.");
160  rxPower = rxParams->m_rxPower_W;
161  }
162  else
163  {
164  NS_FATAL_ERROR(
165  "SatPhyRx::StartRx - too long transmission time: packet started to be "
166  "received in a ground entity while not being fully received on the "
167  "satellite: interferences could not be properly computed.");
168  }
169  }
170  else
171  {
172  rxPower = rxParams->m_rxPower_W * (1 + 1 / rxParams->GetSinr());
173  }
174  }
175 
176  // Add the interference even regardless.
177  return GetInterferenceModel()->Add(rxParams->m_duration, rxPower, GetOwnAddress());
178  }
179  else if (ct == SatEnums::FORWARD_USER_CH)
180  {
181  return GetInterferenceModel()->Add(rxParams->m_duration,
182  rxParams->m_rxPower_W,
183  GetOwnAddress());
184  }
185 
186  NS_FATAL_ERROR("SatSatellitePhyRxCarrier::CreateInterference - Invalid channel type!");
187  return nullptr;
188 }
189 
190 void
192 {
193  NS_LOG_FUNCTION(this << key);
194 
195  NS_LOG_INFO(this << " state: " << GetState());
196 
197  NS_ASSERT(GetState() == RX);
198 
199  rxParams_s packetRxParams = GetStoredRxParams(key);
200 
201  const uint32_t nPackets = packetRxParams.rxParams->m_packetsInBurst.size();
202 
203  DecreaseNumOfRxState(packetRxParams.rxParams->m_txInfo.packetType);
204 
205  // Test if when receiving a packet on ground from transparent satellite, uplink SINR has been
206  // correctly set
208  {
209  NS_ASSERT(packetRxParams.rxParams->HasSinrComputed());
210  }
211 
212  packetRxParams.rxParams->SetInterferencePower(
213  GetInterferenceModel()->Calculate(packetRxParams.interferenceEvent));
214 
215  ReceiveSlot(packetRxParams, nPackets);
216 
217  GetInterferenceModel()->NotifyRxEnd(packetRxParams.interferenceEvent);
218 
220  packetRxParams.interferenceEvent = nullptr;
222 }
223 
224 bool
226  double cSinr,
227  Ptr<SatSignalParameters> rxParams,
228  Ptr<SatInterference::InterferenceChangeEvent> interferenceEvent)
229 {
230  NS_LOG_FUNCTION(this);
231 
232  bool phyError = false;
233 
236  {
239  phyError = GetInterferenceModel()->HasCollision(interferenceEvent);
240  NS_LOG_INFO("Strict collision mode, phyError: " << phyError);
241  }
243  {
245  phyError = CheckAgainstLinkResults(cSinr, rxParams);
246  NS_LOG_INFO("Composite SINR mode, phyError: " << phyError);
247  }
249  {
250  double r = GetUniformRandomValue(0, 1);
252  {
253  phyError = true;
254  }
255  NS_LOG_INFO("Constant collision probability mode, phyError: " << phyError);
256  }
257  else
258  {
259  NS_FATAL_ERROR("SatPhyRxCarrier::ProcessSlottedAlohaCollisions - Random access collision "
260  "model not defined");
261  }
262 
263  return phyError;
264 }
265 
266 void
268  const uint32_t nPackets)
269 {
270  NS_LOG_FUNCTION(this << &packetRxParams << nPackets);
271 
272  NS_ASSERT(packetRxParams.rxParams->m_txInfo.packetType != SatEnums::PACKET_TYPE_CRDSA);
274  double sinr = CalculateSinr(packetRxParams.rxParams->m_rxPower_W,
275  packetRxParams.rxParams->GetInterferencePower(),
280 
281  SatAddressE2ETag addressE2ETag;
282  packetRxParams.rxParams->m_packetsInBurst[0]->PeekPacketTag(addressE2ETag);
283 
284  // Update link specific SINR trace
285  switch (GetChannelType())
286  {
290  break;
294  break;
295  default:
296  NS_FATAL_ERROR("Incorrect channel for satPhyRxCarrierPerSlot: "
298  }
299 
302  bool phyError(false);
303 
305  double cSinr;
306  switch (GetLinkRegenerationMode())
307  {
309  cSinr = CalculateCompositeSinr(sinr, packetRxParams.rxParams->GetSinr());
310  break;
314  cSinr = sinr;
315  break;
316  default:
317  NS_FATAL_ERROR("Incorrect regeneration mode for satPhyRxCarrierPerSlot");
318  }
319 
320  if (!m_cnoCallback.IsNull())
321  {
322  switch (GetLinkRegenerationMode())
323  {
326  double worstSinr = GetWorstSinr(sinr, packetRxParams.rxParams->GetSinr());
327 
332  double cno = (GetLinkRegenerationMode() == SatEnums::TRANSPARENT) ? cSinr : worstSinr;
333 
334  // Forward link
335  switch (GetNodeInfo()->GetNodeType())
336  {
337  case SatEnums::NT_UT:
338  cno = SatUtils::DbToLinear(
340  break;
341  case SatEnums::NT_GW:
344  packetRxParams.rxParams->m_txInfo.waveformId));
345  break;
346  default:
347  NS_FATAL_ERROR("Unsupported node type for a NORMAL Rx model!");
348  }
349 
350  cno *= m_rxBandwidthHz;
351 
352  packetRxParams.rxParams->m_packetsInBurst[0]->PeekPacketTag(addressE2ETag);
353 
354  m_cnoCallback(packetRxParams.rxParams->m_satId,
355  packetRxParams.rxParams->m_beamId,
356  addressE2ETag.GetE2ESourceAddress(),
357  GetOwnAddress(),
358  cno,
359  false);
360  break;
361  }
365  packetRxParams.rxParams->m_packetsInBurst;
366  SatSignalParameters::PacketsInBurst_t::const_iterator i;
367  for (i = packets.begin(); i != packets.end(); i++)
368  {
369  SatUplinkInfoTag satUplinkInfoTag;
370  if (!(*i)->PeekPacketTag(satUplinkInfoTag))
371  {
372  NS_FATAL_ERROR("SatUplinkInfoTag not found !");
373  }
374 
379  double worstCno = GetWorstSinr(sinr, satUplinkInfoTag.GetSinr());
380  double downlinkCno = sinr;
381 
382  // Forward link and return link use same algorithms (because of SCPC)
383  switch (GetNodeInfo()->GetNodeType())
384  {
385  case SatEnums::NT_UT:
386  case SatEnums::NT_GW:
388  SatUtils::LinearToDb(worstCno)));
389  downlinkCno =
391  SatUtils::LinearToDb(downlinkCno)));
392  break;
393  default:
394  NS_FATAL_ERROR("Unsupported node type for a NORMAL Rx model!");
395  }
396 
397  worstCno *= m_rxBandwidthHz;
398  downlinkCno *= m_rxBandwidthHz;
399 
400  (*i)->PeekPacketTag(addressE2ETag);
401 
402  SatMacTag satMacTag;
403  (*i)->PeekPacketTag(satMacTag);
404 
405  m_cnoCallback(satUplinkInfoTag.GetSatId(),
406  satUplinkInfoTag.GetBeamId(),
407  addressE2ETag.GetE2ESourceAddress(),
408  GetOwnAddress(),
409  worstCno,
410  false);
411 
413  GetBeamId(),
414  satMacTag.GetSourceAddress(),
415  GetOwnAddress(),
416  downlinkCno,
417  true);
418  }
419  break;
420  }
421  default:
422  NS_FATAL_ERROR("Incorrect regeneration mode for SatPhyRxCarrierPerSlot");
423  }
424  }
425 
426  // Update composite SINR trace for DAMA and Slotted ALOHA packets
427  m_sinrTrace(SatUtils::LinearToDb(cSinr), packetRxParams.sourceAddress);
428 
431  {
433  }
434 
435  if (packetRxParams.rxParams->m_txInfo.packetType == SatEnums::PACKET_TYPE_SLOTTED_ALOHA)
436  {
437  NS_LOG_INFO("Slotted ALOHA packet received");
438 
439  // Update the load with FEC block size!
440  m_randomAccessBitsInFrame += packetRxParams.rxParams->m_txInfo.fecBlockSizeInBytes *
442 
444  phyError = ProcessSlottedAlohaCollisions(cSinr,
445  packetRxParams.rxParams,
446  packetRxParams.interferenceEvent);
447 
448  if (nPackets > 0)
449  {
450  const bool hasCollision =
451  GetInterferenceModel()->HasCollision(packetRxParams.interferenceEvent);
452  m_slottedAlohaRxCollisionTrace(nPackets, // number of packets
453  packetRxParams.sourceAddress, // sender address
454  hasCollision // collision flag
455  );
456  m_slottedAlohaRxErrorTrace(nPackets, // number of packets
457  packetRxParams.sourceAddress, // sender address
458  phyError // error flag
459  );
460  }
461  }
462  else
463  {
465  phyError = CheckAgainstLinkResults(cSinr, packetRxParams.rxParams);
466 
467  if (nPackets > 0)
468  {
469  switch (GetChannelType())
470  {
473  m_daRxTrace(nPackets, // number of packets
474  packetRxParams.destAddress, // destination address
475  phyError // error flag
476  );
477  break;
480  m_daRxTrace(nPackets, // number of packets
481  packetRxParams.sourceAddress, // destination address
482  phyError // error flag
483  );
484  break;
485  default:
486  NS_FATAL_ERROR("Channel unknown !");
487  }
488  }
489 
491  }
492 
493  switch (GetLinkRegenerationMode())
494  {
497  packetRxParams.rxParams->SetSinr(sinr, m_additionalInterferenceCallback());
498  break;
501  SatSignalParameters::PacketsInBurst_t packets = packetRxParams.rxParams->m_packetsInBurst;
502  SatSignalParameters::PacketsInBurst_t::const_iterator i;
503  for (i = packets.begin(); i != packets.end(); i++)
504  {
505  SatUplinkInfoTag satUplinkInfoTag;
506  (*i)->RemovePacketTag(satUplinkInfoTag);
507  satUplinkInfoTag.SetSinr(sinr, m_additionalInterferenceCallback());
508  (*i)->AddPacketTag(satUplinkInfoTag);
509  }
510  break;
511  }
512  default:
513  NS_FATAL_ERROR("Incorrect regeneration mode for SatPhyRxCarrierPerSlot");
514  }
515 
517  m_linkBudgetTrace(packetRxParams.rxParams,
518  GetOwnAddress(),
519  packetRxParams.destAddress,
520  packetRxParams.rxParams->GetInterferencePower(),
521  cSinr);
522 
524  m_rxCallback(packetRxParams.rxParams, phyError);
525 
526  packetRxParams.rxParams = nullptr;
527 }
528 
529 void
531 {
532  NS_LOG_FUNCTION(this);
533 
534  m_randomAccessDynamicLoadControlNormalizedOfferedLoad.push_back(measuredRandomAccessLoad);
535 
538  {
540  }
541 }
542 
543 double
545 {
546  NS_LOG_FUNCTION(this);
547 
548  double sum = 0.0;
549  double averageNormalizedOfferedLoad = 0.0;
550  std::deque<double>::iterator it;
551 
554  it++)
555  {
556  sum += (*it);
557  }
558 
560  {
561  averageNormalizedOfferedLoad =
563  }
564 
565  NS_LOG_INFO("Average normalized offered load: " << averageNormalizedOfferedLoad);
566 
567  return averageNormalizedOfferedLoad;
568 }
569 
570 } // namespace ns3
This class implements a tag that carries the satellite MAC of GW and UT.
Mac48Address GetE2ESourceAddress(void) const
Get E2E source MAC address.
Mac48Address GetE2EDestAddress(void) const
Get E2E destination MAC address.
ChannelType_t
Types of channel.
static std::string GetChannelTypeName(ChannelType_t channelType)
This class implements a tag that carries the satellite MAC specific information, such as source and d...
Mac48Address GetSourceAddress(void) const
Get source MAC address.
Information of beam users liken UTs and their users.
Base class for all SatPhyRxCarriers.
Ptr< SatInterference > GetInterferenceModel()
Get pointer to the current interference model.
void DoCompositeSinrOutputTrace(double cSinr)
Function for composite SINR output tracing.
void RemoveStoredRxParams(uint32_t key)
Remove stored rxParams under a key.
double m_rxExtNoisePowerW
External noise power system RX noise.
TracedCallback< double, const Address & > m_linkSinrTrace
A callback for link specific SINR in dB.
TracedCallback< uint32_t, const Address & > m_daRxCarrierIdTrace
TracedCallback< Ptr< SatSignalParameters >, Mac48Address, Mac48Address, double, double > m_linkBudgetTrace
The trace source on packet receptiong.
Ptr< SatNodeInfo > GetNodeInfo()
Get the satellite node info.
SatPhyRxCarrierConf::AdditionalInterferenceCallback m_additionalInterferenceCallback
Callback to get additional interference.
uint32_t GetCarrierId() const
Get the ID of the carrier.
void DecreaseNumOfRxState(SatEnums::PacketType_t packetType)
Function for decreasing the number of ongoing transmissions.
virtual SatEnums::RegenerationMode_t GetLinkRegenerationMode()
Get the link regeneration mode.
virtual SatEnums::ChannelType_t GetChannelType()
Get the channel type.
bool IsCompositeSinrOutputTraceEnabled() const
Check if composite SINR output trace is enabled.
uint32_t GetBeamId()
Get ID the ID of the beam this carrier is attached to.
double CalculateSinr(double rxPowerW, double ifPowerW, double rxNoisePowerW, double rxAciIfPowerW, double rxExtNoisePowerW, double otherInterference)
Function for calculating the SINR.
SatPhyRx::ReceiveCallback m_rxCallback
The upper layer package receive callback.
TracedCallback< uint32_t, const Address &, bool > m_daRxTrace
DaRx trace source.
double m_rxAciIfPowerW
RX Adjacent channel interference.
TracedCallback< double, const Address & > m_sinrTrace
A callback for transmission composite SINR at UT (BBFrame) or GW (time slot).
rxParams_s GetStoredRxParams(uint32_t key)
Get stored rxParams under a key.
Ptr< SatChannelEstimationErrorContainer > GetChannelEstimationErrorContainer()
Get a pointer to the channel estimation error container of the carrier.
bool CheckAgainstLinkResults(double cSinr, Ptr< SatSignalParameters > rxParams)
Function for checking the SINR against the link results.
SatPhy::CnoCallback m_cnoCallback
The upper layer C/N0 receive callback.
double CalculateCompositeSinr(double sinr1, double sinr2)
Function for calculating the composite SINR.
double GetWorstSinr(double sinr1, double sinr2)
Function for calculating the worst sinr between uplink and downlink.
virtual void DoDispose()
Dispose.
double GetUniformRandomValue(double min, double max)
A helper method for getting values form a uniform random variable in child classes.
uint32_t GetSatId()
Get ID the ID of the satellite this carrier is attached to.
double m_rxBandwidthHz
RX Bandwidth in Hz.
State GetState()
Get the state of the carrier.
Mac48Address GetOwnAddress()
Get the MAC address of the carrier.
TracedCallback< uint32_t, const Address &, bool > m_slottedAlohaRxCollisionTrace
SlottedAlohaRxCollision trace source.
SatPhyRxCarrierPerSlot(uint32_t carrierId, Ptr< SatPhyRxCarrierConf > carrierConf, Ptr< SatWaveformConf > waveformConf, bool randomAccessEnabled)
Constructor.
static TypeId GetTypeId(void)
Get the TypeId of the class.
virtual void EndRxData(uint32_t key)
Function for ending the packet reception from the SatChannel.
bool ProcessSlottedAlohaCollisions(double cSinr, Ptr< SatSignalParameters > rxParams, Ptr< SatInterference::InterferenceChangeEvent > interferenceEvent)
Function for processing the Slotted ALOHA collisions.
TracedCallback< uint32_t, const Address &, bool > m_slottedAlohaRxErrorTrace
SlottedAlohaRxError trace source.
virtual void ReceiveSlot(SatPhyRxCarrier::rxParams_s packetRxParams, const uint32_t nPackets)
Receive a slot.
virtual void DoDispose()
Dispose implementation.
void SaveMeasuredRandomAccessLoad(double measuredRandomAccessLoad)
Function for saving the measured random access load.
SatPhyRxCarrierConf::RandomAccessCollisionModel m_randomAccessCollisionModel
virtual Ptr< SatInterference::InterferenceChangeEvent > CreateInterference(Ptr< SatSignalParameters > rxParams, Address rxAddress)
Create an interference event based on Rx parameters and address.
uint32_t m_randomAccessBitsInFrame
The number of random access bits in current frame.
std::deque< double > m_randomAccessDynamicLoadControlNormalizedOfferedLoad
double CalculateAverageNormalizedOfferedRandomAccessLoad()
Function for calculating the average normalized offered random access load.
virtual void BeginEndScheduling()
Function for initializing the frame/window end scheduling.
std::vector< Ptr< Packet > > PacketsInBurst_t
Buffer for transmissions.
static T DbToLinear(T db)
Converts decibels to linear.
static T LinearToDb(T linear)
Converts linear to decibels.
constexpr uint32_t BITS_PER_BYTE
Number of bits in a byte.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
Struct for storing the packet specific Rx parameters.
Ptr< SatInterference::InterferenceChangeEvent > interferenceEvent