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 <limits>
34 #include <ostream>
35 #include <utility>
36 
37 NS_LOG_COMPONENT_DEFINE("SatPhyRxCarrierPerSlot");
38 
39 namespace ns3
40 {
41 
42 NS_OBJECT_ENSURE_REGISTERED(SatPhyRxCarrierPerSlot);
43 
45  Ptr<SatPhyRxCarrierConf> carrierConf,
46  Ptr<SatWaveformConf> waveformConf,
47  bool randomAccessEnabled)
48  : SatPhyRxCarrier(carrierId, carrierConf, waveformConf, randomAccessEnabled),
49  m_randomAccessBitsInFrame(0),
50  m_randomAccessAllocationChannelId(0),
51  m_randomAccessCollisionModel(SatPhyRxCarrierConf::RA_COLLISION_NOT_DEFINED),
52  m_randomAccessConstantErrorRate(0.0),
53  m_randomAccessAverageNormalizedOfferedLoadMeasurementWindowSize(0),
54  m_enableRandomAccessDynamicLoadControl(false),
55  m_disableErrorHighTransmissionTime(false)
56 {
57  if (randomAccessEnabled)
58  {
59  m_randomAccessCollisionModel = carrierConf->GetRandomAccessCollisionModel();
60  m_randomAccessConstantErrorRate = carrierConf->GetRandomAccessConstantErrorRate();
62  carrierConf->GetRandomAccessAverageNormalizedOfferedLoadMeasurementWindowSize();
64  carrierConf->IsRandomAccessDynamicLoadControlEnabled();
65 
66  NS_LOG_INFO("RA interference model: "
67  << carrierConf->GetInterferenceModel(true)
68  << ", RA collision model: " << m_randomAccessCollisionModel
69  << ", RA avg. normalized offered load measurement window size: "
71  }
72 }
73 
75 {
76  NS_LOG_FUNCTION(this);
77 }
78 
79 void
81 {
82 }
83 
84 TypeId
86 {
87  static TypeId tid =
88  TypeId("ns3::SatPhyRxCarrierPerSlot")
89  .SetParent<SatPhyRxCarrier>()
90  .AddAttribute(
91  "DisableErrorHighTransmissionTime",
92  "Disable fatal error when transmission time is higher than propagation time, but "
93  "computations are less precise.",
94  BooleanValue(false),
96  MakeBooleanChecker())
97  .AddTraceSource(
98  "SlottedAlohaRxCollision",
99  "Received a packet burst through Random Access Slotted ALOHA",
101  "ns3::SatPhyRxCarrierPacketProbe::RxStatusCallback")
102  .AddTraceSource(
103  "SlottedAlohaRxError",
104  "Received a packet burst through Random Access Slotted ALOHA",
105  MakeTraceSourceAccessor(&SatPhyRxCarrierPerSlot::m_slottedAlohaRxErrorTrace),
106  "ns3::SatPhyRxCarrierPacketProbe::RxStatusCallback");
107  return tid;
108 }
109 
110 void
112 {
113  NS_LOG_FUNCTION(this);
114 
117 }
118 
119 Ptr<SatInterference::InterferenceChangeEvent>
120 SatPhyRxCarrierPerSlot::CreateInterference(Ptr<SatSignalParameters> rxParams, Address senderAddress)
121 {
122  NS_LOG_FUNCTION(this << rxParams << senderAddress);
123 
124  // Case satellite regenerative
126  {
127  return GetInterferenceModel()->Add(rxParams->m_duration,
128  rxParams->m_rxPower_W,
129  GetOwnAddress());
130  }
131 
133  if (ct == SatEnums::RETURN_FEEDER_CH)
134  {
135  // In feeder downlink the interference by UTs in the same
136  // beam (intra-beam interference e.g. due to random access) SHOULD NOT be tracked.
137  // Intra-beam interference is already taken into account at the satellite. Thus,
138  // here we pass intra-beam transmissions with zero interference power to the
139  // interference model.
140  // Rx power in the rxParams is the received power of only one of the interfering
141  // signals of the wanted signal. In reality, we are receiving the same signal
142  // through all the co-channel transponders of the satellite, where the rxPower
143  // is the C and all the other components are considered as interference I.
144  // This can be compensated with the following equation:
145  // rxPower = rxParams->m_rxPower_W * (1 + 1/rxParams->m_sinr);
146  // See more from satellite module documentation.
147 
148  double rxPower(0.0);
149 
150  if (rxParams->m_beamId != GetBeamId())
151  {
152  if (!rxParams->HasSinrComputed())
153  {
155  {
156  NS_LOG_WARN("SatPhyRx::StartRx - too long transmission time: packet started to "
157  "be received in a ground entity while not being fully received on "
158  "the satellite: interferences could not be properly computed.");
159  rxPower = rxParams->m_rxPower_W;
160  }
161  else
162  {
163  NS_FATAL_ERROR(
164  "SatPhyRx::StartRx - too long transmission time: packet started to be "
165  "received in a ground entity while not being fully received on the "
166  "satellite: interferences could not be properly computed.");
167  }
168  }
169  else
170  {
171  rxPower = rxParams->m_rxPower_W * (1 + 1 / rxParams->GetSinr());
172  }
173  }
174 
175  // Add the interference even regardless.
176  return GetInterferenceModel()->Add(rxParams->m_duration, rxPower, GetOwnAddress());
177  }
178  else if (ct == SatEnums::FORWARD_USER_CH)
179  {
180  return GetInterferenceModel()->Add(rxParams->m_duration,
181  rxParams->m_rxPower_W,
182  GetOwnAddress());
183  }
184 
185  NS_FATAL_ERROR("SatSatellitePhyRxCarrier::CreateInterference - Invalid channel type!");
186  return NULL;
187 }
188 
189 void
191 {
192  NS_LOG_FUNCTION(this);
193  NS_LOG_INFO(this << " state: " << GetState());
194 
195  NS_ASSERT(GetState() == RX);
196 
197  rxParams_s packetRxParams = GetStoredRxParams(key);
198 
199  const uint32_t nPackets = packetRxParams.rxParams->m_packetsInBurst.size();
200 
201  DecreaseNumOfRxState(packetRxParams.rxParams->m_txInfo.packetType);
202 
203  // Test if when receiving a packet on ground from transparent satellite, uplink SINR has been
204  // correctly set
206  {
207  NS_ASSERT(packetRxParams.rxParams->HasSinrComputed());
208  }
209 
210  packetRxParams.rxParams->SetInterferencePower(
211  GetInterferenceModel()->Calculate(packetRxParams.interferenceEvent));
212 
213  ReceiveSlot(packetRxParams, nPackets);
214 
215  GetInterferenceModel()->NotifyRxEnd(packetRxParams.interferenceEvent);
216 
218  packetRxParams.interferenceEvent = NULL;
220 }
221 
222 bool
224  double cSinr,
225  Ptr<SatSignalParameters> rxParams,
226  Ptr<SatInterference::InterferenceChangeEvent> interferenceEvent)
227 {
228  NS_LOG_FUNCTION(this);
229 
230  bool phyError = false;
231 
234  {
237  phyError = GetInterferenceModel()->HasCollision(interferenceEvent);
238  NS_LOG_INFO("Strict collision mode, phyError: " << phyError);
239  }
241  {
243  phyError = CheckAgainstLinkResults(cSinr, rxParams);
244  NS_LOG_INFO("Composite SINR mode, phyError: " << phyError);
245  }
247  {
248  double r = GetUniformRandomValue(0, 1);
250  {
251  phyError = true;
252  }
253  NS_LOG_INFO("Constant collision probability mode, phyError: " << phyError);
254  }
255  else
256  {
257  NS_FATAL_ERROR("SatPhyRxCarrier::ProcessSlottedAlohaCollisions - Random access collision "
258  "model not defined");
259  }
260 
261  return phyError;
262 }
263 
264 void
266  const uint32_t nPackets)
267 {
268  NS_LOG_FUNCTION(this << &packetRxParams << nPackets);
269 
270  NS_ASSERT(packetRxParams.rxParams->m_txInfo.packetType != SatEnums::PACKET_TYPE_CRDSA);
272  double sinr = CalculateSinr(packetRxParams.rxParams->m_rxPower_W,
273  packetRxParams.rxParams->GetInterferencePower(),
278 
279  SatAddressE2ETag addressE2ETag;
280  packetRxParams.rxParams->m_packetsInBurst[0]->PeekPacketTag(addressE2ETag);
281 
282  // Update link specific SINR trace
283  switch (GetChannelType())
284  {
288  break;
292  break;
293  default:
294  NS_FATAL_ERROR("Incorrect channel for satPhyRxCarrierPerSlot: "
296  }
297 
300  bool phyError(false);
301 
303  double cSinr;
304  switch (GetLinkRegenerationMode())
305  {
307  cSinr = CalculateCompositeSinr(sinr, packetRxParams.rxParams->GetSinr());
308  break;
312  cSinr = sinr;
313  break;
314  default:
315  NS_FATAL_ERROR("Incorrect regeneration mode for satPhyRxCarrierPerSlot");
316  }
317 
318  if (!m_cnoCallback.IsNull())
319  {
320  switch (GetLinkRegenerationMode())
321  {
324  double worstSinr = GetWorstSinr(sinr, packetRxParams.rxParams->GetSinr());
325 
330  double cno = (GetLinkRegenerationMode() == SatEnums::TRANSPARENT) ? cSinr : worstSinr;
331 
332  // Forward link
333  switch (GetNodeInfo()->GetNodeType())
334  {
335  case SatEnums::NT_UT:
336  cno = SatUtils::DbToLinear(
338  break;
339  case SatEnums::NT_GW:
342  packetRxParams.rxParams->m_txInfo.waveformId));
343  break;
344  default:
345  NS_FATAL_ERROR("Unsupported node type for a NORMAL Rx model!");
346  }
347 
348  cno *= m_rxBandwidthHz;
349 
350  packetRxParams.rxParams->m_packetsInBurst[0]->PeekPacketTag(addressE2ETag);
351 
352  m_cnoCallback(packetRxParams.rxParams->m_satId,
353  packetRxParams.rxParams->m_beamId,
354  addressE2ETag.GetE2ESourceAddress(),
355  GetOwnAddress(),
356  cno,
357  false);
358  break;
359  }
363  packetRxParams.rxParams->m_packetsInBurst;
364  SatSignalParameters::PacketsInBurst_t::const_iterator i;
365  for (i = packets.begin(); i != packets.end(); i++)
366  {
367  SatUplinkInfoTag satUplinkInfoTag;
368  if (!(*i)->PeekPacketTag(satUplinkInfoTag))
369  {
370  NS_FATAL_ERROR("SatUplinkInfoTag not found !");
371  }
372 
377  double worstCno = GetWorstSinr(sinr, satUplinkInfoTag.GetSinr());
378  double downlinkCno = sinr;
379 
380  // Forward link and return link use same algorithms (because of SCPC)
381  switch (GetNodeInfo()->GetNodeType())
382  {
383  case SatEnums::NT_UT:
384  case SatEnums::NT_GW:
386  SatUtils::LinearToDb(worstCno)));
387  downlinkCno =
389  SatUtils::LinearToDb(downlinkCno)));
390  break;
391  default:
392  NS_FATAL_ERROR("Unsupported node type for a NORMAL Rx model!");
393  }
394 
395  worstCno *= m_rxBandwidthHz;
396  downlinkCno *= m_rxBandwidthHz;
397 
398  (*i)->PeekPacketTag(addressE2ETag);
399 
400  SatMacTag satMacTag;
401  (*i)->PeekPacketTag(satMacTag);
402 
403  m_cnoCallback(satUplinkInfoTag.GetSatId(),
404  satUplinkInfoTag.GetBeamId(),
405  addressE2ETag.GetE2ESourceAddress(),
406  GetOwnAddress(),
407  worstCno,
408  false);
409 
411  GetBeamId(),
412  satMacTag.GetSourceAddress(),
413  GetOwnAddress(),
414  downlinkCno,
415  true);
416  }
417  break;
418  }
419  default:
420  NS_FATAL_ERROR("Incorrect regeneration mode for SatPhyRxCarrierPerSlot");
421  }
422  }
423 
424  // Update composite SINR trace for DAMA and Slotted ALOHA packets
425  m_sinrTrace(SatUtils::LinearToDb(cSinr), packetRxParams.sourceAddress);
426 
429  {
431  }
432 
433  if (packetRxParams.rxParams->m_txInfo.packetType == SatEnums::PACKET_TYPE_SLOTTED_ALOHA)
434  {
435  NS_LOG_INFO("Slotted ALOHA packet received");
436 
437  // Update the load with FEC block size!
438  m_randomAccessBitsInFrame += packetRxParams.rxParams->m_txInfo.fecBlockSizeInBytes *
440 
442  phyError = ProcessSlottedAlohaCollisions(cSinr,
443  packetRxParams.rxParams,
444  packetRxParams.interferenceEvent);
445 
446  if (nPackets > 0)
447  {
448  const bool hasCollision =
449  GetInterferenceModel()->HasCollision(packetRxParams.interferenceEvent);
450  m_slottedAlohaRxCollisionTrace(nPackets, // number of packets
451  packetRxParams.sourceAddress, // sender address
452  hasCollision // collision flag
453  );
454  m_slottedAlohaRxErrorTrace(nPackets, // number of packets
455  packetRxParams.sourceAddress, // sender address
456  phyError // error flag
457  );
458  }
459  }
460  else
461  {
463  phyError = CheckAgainstLinkResults(cSinr, packetRxParams.rxParams);
464 
465  if (nPackets > 0)
466  {
467  switch (GetChannelType())
468  {
471  m_daRxTrace(nPackets, // number of packets
472  packetRxParams.destAddress, // destination address
473  phyError // error flag
474  );
475  break;
478  m_daRxTrace(nPackets, // number of packets
479  packetRxParams.sourceAddress, // destination address
480  phyError // error flag
481  );
482  break;
483  default:
484  NS_FATAL_ERROR("Channel unknown !");
485  }
486  }
487 
489  }
490 
491  switch (GetLinkRegenerationMode())
492  {
495  packetRxParams.rxParams->SetSinr(sinr, m_additionalInterferenceCallback());
496  break;
499  SatSignalParameters::PacketsInBurst_t packets = packetRxParams.rxParams->m_packetsInBurst;
500  SatSignalParameters::PacketsInBurst_t::const_iterator i;
501  for (i = packets.begin(); i != packets.end(); i++)
502  {
503  SatUplinkInfoTag satUplinkInfoTag;
504  (*i)->RemovePacketTag(satUplinkInfoTag);
505  satUplinkInfoTag.SetSinr(sinr, m_additionalInterferenceCallback());
506  (*i)->AddPacketTag(satUplinkInfoTag);
507  }
508  break;
509  }
510  default:
511  NS_FATAL_ERROR("Incorrect regeneration mode for SatPhyRxCarrierPerSlot");
512  }
513 
515  m_linkBudgetTrace(packetRxParams.rxParams,
516  GetOwnAddress(),
517  packetRxParams.destAddress,
518  packetRxParams.rxParams->GetInterferencePower(),
519  cSinr);
520 
522  m_rxCallback(packetRxParams.rxParams, phyError);
523 
524  packetRxParams.rxParams = NULL;
525 }
526 
527 void
529 {
530  NS_LOG_FUNCTION(this);
531 
532  m_randomAccessDynamicLoadControlNormalizedOfferedLoad.push_back(measuredRandomAccessLoad);
533 
536  {
538  }
539 }
540 
541 double
543 {
544  NS_LOG_FUNCTION(this);
545 
546  double sum = 0.0;
547  double averageNormalizedOfferedLoad = 0.0;
548  std::deque<double>::iterator it;
549 
552  it++)
553  {
554  sum += (*it);
555  }
556 
558  {
559  averageNormalizedOfferedLoad =
561  }
562 
563  NS_LOG_INFO("Average normalized offered load: " << averageNormalizedOfferedLoad);
564 
565  return averageNormalizedOfferedLoad;
566 }
567 
568 } // 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