satellite-phy-rx-carrier-per-window.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2018 CNES
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Joaquin Muguerza <jmuguerza@toulouse.viveris.fr>
19  */
20 
22 
23 #include "satellite-link-results.h"
26 #include "satellite-utils.h"
28 
29 #include <ns3/boolean.h>
30 #include <ns3/double.h>
31 #include <ns3/log.h>
32 #include <ns3/simulator.h>
33 
34 #include <algorithm>
35 #include <iomanip>
36 #include <limits>
37 #include <ostream>
38 #include <utility>
39 
40 NS_LOG_COMPONENT_DEFINE("SatPhyRxCarrierPerWindow");
41 
42 namespace ns3
43 {
44 
45 NS_OBJECT_ENSURE_REGISTERED(SatPhyRxCarrierPerWindow);
46 
48  Ptr<SatPhyRxCarrierConf> carrierConf,
49  Ptr<SatWaveformConf> waveformConf,
50  bool randomAccessEnabled)
51  : SatPhyRxCarrierPerSlot(carrierId, carrierConf, waveformConf, randomAccessEnabled),
52  m_windowDuration(MilliSeconds(60)),
53  m_windowStep(MilliSeconds(20)),
54  m_windowDelay(Seconds(0)),
55  m_firstWindow(Seconds(0)),
56  m_windowSicIterations(10),
57  m_spreadingFactor(0),
58  m_windowEndSchedulingInitialized(false),
59  m_detectionThreshold(0.0),
60  m_sicEnabled(true)
61 {
62  NS_LOG_FUNCTION(this);
63  NS_LOG_INFO("Constructor called with arguments " << carrierId << ", " << carrierConf << ", and "
64  << randomAccessEnabled);
65 
66  NS_ASSERT(m_randomAccessEnabled == true);
67 }
68 
69 void
71 {
72  NS_LOG_FUNCTION(this);
74  {
75  if (GetNodeInfo() == NULL)
76  {
77  NS_FATAL_ERROR("SatPhyRxWindow::BeginWindowEndScheduling - m_nodeInfo not set");
78  }
79 
81 
84  Simulator::ScheduleWithContext(GetNodeInfo()->GetNodeId(),
87  this);
88  }
89 }
90 
92 {
93  NS_LOG_FUNCTION(this);
94 }
95 
96 TypeId
98 {
99  static TypeId tid =
100  TypeId("ns3::SatPhyRxCarrierPerWindow")
101  .SetParent<SatPhyRxCarrierPerSlot>()
102  .AddAttribute("WindowDuration",
103  "The duration of the sliding window",
104  TimeValue(MilliSeconds(60)),
106  MakeTimeChecker())
107  .AddAttribute("WindowStep",
108  "The length of the step between two window iterations",
109  TimeValue(MilliSeconds(20)),
110  MakeTimeAccessor(&SatPhyRxCarrierPerWindow::m_windowStep),
111  MakeTimeChecker())
112  .AddAttribute(
113  "WindowDelay",
114  "The delay before processing a sliding window, waiting for incomplete packets",
115  TimeValue(Seconds(0)),
116  MakeTimeAccessor(&SatPhyRxCarrierPerWindow::m_windowDelay),
117  MakeTimeChecker())
118  .AddAttribute("FirstWindow",
119  "The time at which the first window is processed",
120  TimeValue(Seconds(0)),
121  MakeTimeAccessor(&SatPhyRxCarrierPerWindow::m_firstWindow),
122  MakeTimeChecker())
123  .AddAttribute("WindowSICIterations",
124  "The number of SIC iterations performed on each window",
125  UintegerValue(10),
127  MakeUintegerChecker<uint32_t>())
128  // TODO: this shouldn't be here!! find a way to retrieve SF from SuperFrameConf,
129  // maybe store SF in waveform.
130  .AddAttribute("SpreadingFactor",
131  "The spreading factor of the packets",
132  UintegerValue(1),
133  MakeUintegerAccessor(&SatPhyRxCarrierPerWindow::m_spreadingFactor),
134  MakeUintegerChecker<uint32_t>())
135  .AddAttribute("DetectionThreshold",
136  "The SNIR Detection Threshold (in magnitude) for a packet",
137  DoubleValue(0.0),
139  MakeDoubleChecker<double>(0, std::numeric_limits<double>::max()))
140  .AddAttribute("EnableSIC",
141  "Use SIC when decoding a packet",
142  BooleanValue(true),
143  MakeBooleanAccessor(&SatPhyRxCarrierPerWindow::m_sicEnabled),
144  MakeBooleanChecker())
145  .AddTraceSource(
146  "EssaRxCollision",
147  "Received a packet through Random Access ESSA",
148  MakeTraceSourceAccessor(&SatPhyRxCarrierPerWindow::m_essaRxCollisionTrace),
149  "ns3::SatPhyRxCarrierPacketProbe::RxStatusCallback")
150  .AddTraceSource("EssaRxError",
151  "Received a packet through Random Access ESSA",
152  MakeTraceSourceAccessor(&SatPhyRxCarrierPerWindow::m_essaRxErrorTrace),
153  "ns3::SatPhyRxCarrierPacketProbe::RxStatusCallback")
154  .AddTraceSource("WindowLoad",
155  "Performed a window load measurement",
156  MakeTraceSourceAccessor(&SatPhyRxCarrierPerWindow::m_windowLoadTrace),
157  "ns3::SatPhyRxCarrierPerWindow::WindowLoadTraceCallback");
158  return tid;
159 }
160 
161 void
163 {
165 }
166 
167 void
169  const uint32_t nPackets)
170 {
171  NS_ASSERT(packetRxParams.rxParams->m_txInfo.packetType !=
173 
174  if (packetRxParams.rxParams->m_txInfo.packetType != SatEnums::PACKET_TYPE_ESSA)
175  {
176  NS_LOG_ERROR("SatPhyRxCarrierPerWindow::ReceiveSlot - Time: "
177  << Now().GetSeconds() << " - Non ESSA packet received");
178  return;
179  }
180 
181  NS_LOG_INFO("SatPhyRxCarrierPerWindow::ReceiveSlot - Time: " << Now().GetSeconds()
182  << " - ESSA packet received");
183 
185 
186  params.destAddress = packetRxParams.destAddress;
187  params.sourceAddress = packetRxParams.sourceAddress;
188  params.duration = packetRxParams.rxParams->m_duration;
189  params.arrivalTime = Now() - params.duration; // arrival time is the start of reception
190  params.rxParams = packetRxParams.rxParams;
191  params.hasBeenDecoded = false;
192  params.failedSic = false;
193  params.hasBeenUpdated = false;
194  params.isInsideWindow = false;
195  params.meanSinr = -1.0;
196  params.preambleMeanSinr = -1.0;
197 
198  // Calculate SINR, gamma and ifPowerPerFragment
200 
201  // Check if packet can be detected
202  if (!PacketCanBeDetected(params))
203  {
204  NS_LOG_INFO("SatPhyRxCarrierPerWindow::ReceiveSlot - Packet "
205  << params.rxParams->m_txInfo.crdsaUniquePacketId << " from "
206  << params.sourceAddress << " cannot be detected. Ignore it.");
208  m_essaRxCollisionTrace(1, // number of packets
209  params.sourceAddress, // sender address
210  1); // error flag
211  return;
212  }
213 
214  // Eliminate interference from already decoded packets
215  // WARNING: with some combinations of window size and step, it may be possible that
216  // previously decoded packets have already been cleaned.
218 
219  // Calculate SINR, gamma and ifPowerPerFragment
221 
222  AddEssaPacket(params);
223 }
224 
225 void
228 {
229  NS_LOG_FUNCTION(this);
230 
231  if (!m_sicEnabled)
232  {
233  return;
234  }
235 
236  NS_LOG_INFO("SatPhyRxCarrierPerWindow::EliminatePreviousInterferences - Eliminate "
237  "interferences from packet "
238  << packet.rxParams->m_txInfo.crdsaUniquePacketId << " from "
239  << packet.sourceAddress);
240 
241  // Get which packets that have been decoded interfere with this packet
242  packetList_t::iterator packet_it;
243  for (packet_it = m_essaPacketContainer.begin(); packet_it != m_essaPacketContainer.end();
244  packet_it++)
245  {
247  if ((packet_it->arrivalTime + packet_it->duration) <= packet.arrivalTime)
248  {
249  continue;
250  }
252  if (!(packet_it->hasBeenDecoded))
253  {
254  continue;
255  }
257  std::pair<double, double> normalizedTimes =
258  GetNormalizedPacketInterferenceTime(packet, *packet_it);
259 
260  NS_LOG_INFO("SatPhyRxCarrierPerWindow::EliminatePreviousInterferences - eliminate "
261  "interference with packet "
262  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId << " from "
263  << packet_it->sourceAddress);
265  GetInterferenceEliminationModel()->EliminateInterferences(
266  packet.rxParams,
267  packet_it->rxParams,
268  packet_it->meanSinr * m_spreadingFactor,
270  normalizedTimes.first,
271  normalizedTimes.second);
272  }
273 }
274 
275 void
278 {
279  NS_LOG_FUNCTION(this);
280  NS_LOG_INFO("SatPhyRxCarrierPerWindow::CalculatePacketInterferenceVectors - Packet "
281  << packet.rxParams->m_txInfo.crdsaUniquePacketId << " from "
282  << packet.sourceAddress);
283 
284  // TODO: should we check the interference model used ?
285  // TODO: should we check the collision model used (check against sinr, collision always drops,
286  // etc) ?
287 
288  double snr = CalculateSinr(packet.rxParams->m_rxPower_W,
289  0.0,
294 
295  double cSnr;
297  {
299  double snrSatellite = CalculateSinr(packet.rxParams->GetRxPowerInSatellite(),
300  0.0,
301  packet.rxParams->GetRxNoisePowerInSatellite(),
302  packet.rxParams->GetRxAciIfPowerInSatellite(),
303  packet.rxParams->GetRxExtNoisePowerInSatellite(),
304  packet.rxParams->GetAdditionalInterference());
305 
306  cSnr = CalculateCompositeSinr(snr, snrSatellite);
307  }
308  else
309  {
310  cSnr = snr;
311  }
312 
314  if (packet.meanSinr < 0.0)
315  {
316  SatSignalParameters::PacketsInBurst_t packets = packet.rxParams->m_packetsInBurst;
317  SatSignalParameters::PacketsInBurst_t::const_iterator i;
318  for (i = packets.begin(); i != packets.end(); i++)
319  {
320  SatUplinkInfoTag satUplinkInfoTag;
321  (*i)->RemovePacketTag(satUplinkInfoTag);
322  satUplinkInfoTag.SetSinr(snr, m_additionalInterferenceCallback());
323  (*i)->AddPacketTag(satUplinkInfoTag);
324  }
325 
326  // Update link specific SINR trace
328 
329  // Update composite SNR trace for DAMA and Slotted ALOHA packets
330  // m_sinrTrace (SatUtils::LinearToDb (cSnr), packet.sourceAddress); // Done with effective
331  // SINR
332 
333  m_linkBudgetTrace(packet.rxParams, GetOwnAddress(), packet.destAddress, 0.0, cSnr);
334 
337  {
339  }
340 
341  NS_LOG_INFO("SatPhyRxCarrierPerWindow::CalculatePacketInterferenceVectors - Received "
342  "packet SNR dB = "
343  << SatUtils::LinearToDb(cSnr));
344  }
345 
347  packet.gamma.clear();
348 
349  std::vector<std::pair<double, double>> interferencePowerPerFragment =
350  packet.rxParams->GetInterferencePowerPerFragment();
351  std::vector<std::pair<double, double>>::iterator interferencePower =
352  interferencePowerPerFragment.begin();
353  double normalizedTime = interferencePower->first, normalizedTimeInSatellite = 0.0;
360  {
361  std::vector<std::pair<double, double>> interferencePowerPerFragmentInSatellite =
362  packet.rxParams->GetInterferencePowerInSatellitePerFragment();
363  for (std::vector<std::pair<double, double>>::iterator interferencePowerInSatellite =
364  interferencePowerPerFragmentInSatellite.begin();
365  interferencePowerInSatellite != interferencePowerPerFragmentInSatellite.end();
366  interferencePowerInSatellite++)
367  {
368  normalizedTimeInSatellite += interferencePowerInSatellite->first;
371  if (normalizedTimeInSatellite > normalizedTime)
372  {
373  interferencePower++;
374  normalizedTime += interferencePower->first;
375  }
376 
379 
381  double cI = (packet.rxParams->GetRxPowerInSatellite() * packet.rxParams->m_rxPower_W) /
382  (interferencePowerInSatellite->second * packet.rxParams->m_rxPower_W +
383  interferencePower->second * packet.rxParams->GetRxPowerInSatellite());
384 
386  double gamma = 1 / (1 / cI + 1 / cSnr);
387  packet.gamma.emplace_back(interferencePowerInSatellite->first, gamma);
388  }
389  }
390  else
391  {
394 
396  double cI = (packet.rxParams->m_rxPower_W) /
397  (packet.rxParams->m_rxPower_W + interferencePower->second);
398 
400  double gamma = 1 / (1 / cI + 1 / cSnr);
401  packet.gamma.emplace_back(1, gamma);
402  }
403 
405  std::vector<std::pair<double, double>> gammaPreamble;
406  Ptr<SatWaveform> wf = GetWaveformConf()->GetWaveform(packet.rxParams->m_txInfo.waveformId);
407  normalizedTime = 0.0;
408  double normalizedPreambleTime =
409  wf->GetPreambleLengthInSymbols() /
410  wf->GetBurstLengthInSymbols(); // This asumes that preamble and burst have the same symbol
411  // rate
412  for (std::vector<std::pair<double, double>>::iterator it = packet.gamma.begin();
413  it != packet.gamma.end();
414  it++)
415  {
416  if (normalizedTime + it->first > normalizedPreambleTime)
417  {
418  gammaPreamble.emplace_back(1.0 - normalizedTime, it->second);
419  break;
420  }
421  gammaPreamble.emplace_back(it->first / normalizedPreambleTime, it->second);
422  normalizedTime += it->first;
423  }
424 
426  packet.meanSinr = SatUtils::ScalarProduct(packet.gamma);
427  packet.preambleMeanSinr = SatUtils::ScalarProduct(gammaPreamble);
428 
429  packet.hasBeenUpdated = true;
430 }
431 
432 void
434 {
435  NS_LOG_FUNCTION(this);
436  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoWindowEnd");
437 
438  // ProcessWindow (Now () - m_windowDuration, Now ());
439  Simulator::Schedule(m_windowDelay,
441  this,
442  Now() - m_windowDuration,
443  Now());
444 
445  // Advance the window (schedule DoWindowEnd for m_windowStep)
446  Simulator::Schedule(m_windowStep, &SatPhyRxCarrierPerWindow::DoWindowEnd, this);
447 }
448 
449 void
450 SatPhyRxCarrierPerWindow::ProcessWindow(Time startTime, Time endTime)
451 {
452  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoProcessWindow - Process window between "
453  << startTime.GetSeconds() << " and " << endTime.GetSeconds());
454 
456  CleanOldPackets(startTime);
457 
459  std::pair<packetList_t::iterator, packetList_t::iterator> windowBounds =
460  GetWindowBounds(startTime, endTime);
461 
462  uint32_t i = 0;
463  while (i < m_windowSicIterations)
464  {
465  while (true)
466  {
468  packetList_t::iterator packet_it = GetHighestSnirPacket(windowBounds);
469  if (packet_it == windowBounds.second)
470  {
471  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoWindowEnd - No more packets to decode");
472  break;
473  }
474  packet_it->hasBeenTreatedInWindow = true;
475 
476  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoWindowEnd - Process packet "
477  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId << " from "
478  << packet_it->sourceAddress);
480  packet_it->hasBeenUpdated = false;
482  double sinrEffective = GetEffectiveSnir(*packet_it);
483  m_sinrTrace(SatUtils::LinearToDb(sinrEffective), packet_it->sourceAddress);
485  bool phyError = CheckAgainstLinkResults(sinrEffective, packet_it->rxParams);
486  // Trace if the packet has been decoded or not
487  m_essaRxErrorTrace(1, // number of packets
488  packet_it->sourceAddress, // sender address
489  phyError); // error flag
490  if (!phyError)
491  {
492  packet_it->hasBeenDecoded = true;
494  DoSic(packet_it, windowBounds);
496  NS_LOG_WARN("received " << packet_it->sourceAddress << " "
497  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId << " "
498  << " INFO " << *(packet_it->rxParams->m_packetsInBurst[0]));
499  }
500  else
501  {
502  NS_LOG_INFO("Failed to decode packet "
503  << packet_it->sourceAddress << "-"
504  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId);
505  packet_it->failedSic = true;
506  }
507  }
508 
509  // increase iteration number
510  i++;
511  }
513  for (packetList_t::iterator packet_it = windowBounds.first; packet_it != windowBounds.second;
514  packet_it++)
515  {
517  if (!packet_it->isInsideWindow || !packet_it->hasBeenTreatedInWindow)
518  {
519  continue;
520  }
521  m_rxCallback(packet_it->rxParams, !packet_it->hasBeenDecoded);
524  }
527  {
529  }
530  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoWindowEnd - Window processing finished");
531 }
532 
533 void
535  packetList_t::iterator processedPacket,
536  std::pair<packetList_t::iterator, packetList_t::iterator> windowBounds)
537 {
538  NS_LOG_FUNCTION(this);
539 
540  if (!m_sicEnabled)
541  {
542  return;
543  }
544 
545  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoSic - eliminate interference from packet "
546  << processedPacket->rxParams->m_txInfo.crdsaUniquePacketId << " from "
547  << processedPacket->sourceAddress);
548 
550  for (packetList_t::iterator packet_it = windowBounds.first; packet_it != windowBounds.second;
551  packet_it++)
552  {
554  if (packet_it->arrivalTime >= processedPacket->arrivalTime + processedPacket->duration)
555  {
556  break;
557  }
559  if (packet_it->arrivalTime + packet_it->duration <= processedPacket->arrivalTime)
560  {
561  continue;
562  }
564  if (packet_it == processedPacket || packet_it->hasBeenDecoded)
565  {
566  continue;
567  }
568  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoSic - eliminate interference with packet "
569  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId << " from "
570  << packet_it->sourceAddress);
572  std::pair<double, double> normalizedTimes =
573  GetNormalizedPacketInterferenceTime(*packet_it, *processedPacket);
575  GetInterferenceEliminationModel()->EliminateInterferences(
576  packet_it->rxParams,
577  processedPacket->rxParams,
578  processedPacket->meanSinr * m_spreadingFactor,
580  normalizedTimes.first,
581  normalizedTimes.second);
582 
584  }
585 }
586 
587 std::pair<double, double>
590  const SatPhyRxCarrierPerWindow::essaPacketRxParams_s& interferingPacket)
591 {
592  NS_LOG_FUNCTION(this);
593 
597  double startTimeA =
598  std::max(0.0,
599  1.0 - ((packet.duration.GetDouble() + packet.arrivalTime.GetDouble() -
600  interferingPacket.arrivalTime.GetDouble()) /
601  packet.duration.GetDouble()));
602  double endTimeA = std::min(
603  1.0,
604  1.0 - (packet.arrivalTime.GetDouble() - interferingPacket.arrivalTime.GetDouble()) /
605  packet.duration.GetDouble());
606  double startTimeB =
607  std::max(0.0,
608  (interferingPacket.arrivalTime.GetDouble() - packet.arrivalTime.GetDouble()) /
609  packet.duration.GetDouble());
610  double endTimeB =
611  std::min(1.0,
612  2.0 - (packet.arrivalTime.GetDouble() - interferingPacket.arrivalTime.GetDouble() +
613  packet.duration.GetDouble()) /
614  packet.duration.GetDouble());
615 
617  // some rounding errors)
618  double normalizedTime = 0.0;
619  double exactStartTime = (startTimeA == 0.0) ? 0.0 : -1.0;
620  double exactEndTime = -1.0;
621  auto ifPowerPerFragment = packet.rxParams->GetInterferencePowerInSatellitePerFragment();
622  for (std::pair<double, double>& ifPower : ifPowerPerFragment)
623  {
624  normalizedTime += ifPower.first;
625  if ((exactStartTime < 0) && (normalizedTime == startTimeA || normalizedTime == startTimeB))
626  {
627  exactStartTime = normalizedTime;
628  }
629  if ((exactEndTime < 0) && (normalizedTime == endTimeA || normalizedTime == endTimeB))
630  {
631  exactEndTime = normalizedTime;
632  }
633  }
634 
635  if ((exactStartTime < 0) || (exactEndTime < 0))
636  {
637  NS_FATAL_ERROR("Cannot find exact interference time between two packets");
638  }
639 
640  return std::make_pair(exactStartTime, exactEndTime);
641 }
642 
643 double
646 {
647  NS_LOG_FUNCTION(this);
648 
649  Ptr<SatLinkResultsRtn> satLinkResults = GetLinkResults()->GetObject<SatLinkResultsFSim>();
650  Ptr<SatMutualInformationTable> mutualInformationTable;
651  if (satLinkResults != NULL)
652  {
653  mutualInformationTable =
655  }
656  else
657  {
658  mutualInformationTable =
659  (GetLinkResults()->GetObject<SatLinkResultsLora>())->GetMutualInformationTable();
660  }
661  double beta = mutualInformationTable->GetBeta();
662 
663  double meanMutualInformation = 0.0;
664  for (std::vector<std::pair<double, double>>::const_iterator it = packet.gamma.begin();
665  it != packet.gamma.end();
666  it++)
667  {
668  meanMutualInformation += it->first * mutualInformationTable->GetNormalizedSymbolInformation(
669  SatUtils::LinearToDb(it->second / beta));
670  }
671 
672  double effectiveSnir =
673  beta * SatUtils::DbToLinear(mutualInformationTable->GetSnirDb(meanMutualInformation));
674 
675  NS_LOG_INFO("SatPhyRxCarrierPerWindow::GetEffectiveSnir - Packet "
676  << packet.rxParams->m_txInfo.crdsaUniquePacketId << " from " << packet.sourceAddress
677  << " - Effective SNIR dB: " << SatUtils::LinearToDb(effectiveSnir));
678 
679  return effectiveSnir;
680 }
681 
682 void
683 SatPhyRxCarrierPerWindow::CleanOldPackets(const Time windowStartTime)
684 {
685  NS_LOG_FUNCTION(this);
686  NS_LOG_INFO("SatPhyRxCarrierPerWindow::CleanOldPackets");
687 
688  packetList_t::iterator it = m_essaPacketContainer.begin();
689  while (it != m_essaPacketContainer.end())
690  {
692  Time offset = it->arrivalTime - windowStartTime;
693  if (offset.IsStrictlyPositive())
694  {
695  break;
696  }
698  offset = it->arrivalTime + it->duration - windowStartTime;
699  if (!offset.IsStrictlyPositive())
700  {
701  // Only trace packets that arrived after first Window
702  if (it->arrivalTime >= m_firstWindow)
703  {
704  if (!(it->hasBeenDecoded))
705  {
706  }
707  else
708  {
709  m_daRxTrace(1, // number of packets
710  it->sourceAddress, // sender address
711  it->failedSic // error flag
712  );
713  }
714  // Trace if the packet has been decoded or not
715  m_essaRxCollisionTrace(1, // number of packets
716  it->sourceAddress, // sender address
717  !(it->hasBeenDecoded)); // error flag
718  }
719  // Delete element from list
720  NS_LOG_INFO("SatPhyRxCarrierPerWindow::CleanOldPackets - Remove packet "
721  << it->rxParams->m_txInfo.crdsaUniquePacketId << " from "
722  << it->sourceAddress);
723  it->rxParams = NULL;
724  m_essaPacketContainer.erase(it++);
725  }
726  else
727  {
728  ++it;
729  }
730  }
731 }
732 
733 std::pair<SatPhyRxCarrierPerWindow::packetList_t::iterator,
734  SatPhyRxCarrierPerWindow::packetList_t::iterator>
735 SatPhyRxCarrierPerWindow::GetWindowBounds(Time startTime, Time endTime)
736 {
737  NS_LOG_FUNCTION(this);
738  NS_LOG_INFO("SatPhyRxCarrierPerWindow::GetWindowBounds");
739 
740  packetList_t::iterator last;
742 
743  for (last = m_essaPacketContainer.begin(); last != m_essaPacketContainer.end(); last++)
744  {
746  last->isInsideWindow = false;
748  if (last->arrivalTime > endTime)
749  {
750  break;
751  }
753  if ((last->arrivalTime >= startTime) && (last->arrivalTime + last->duration <= endTime))
754  {
755  last->isInsideWindow = true;
756  last->hasBeenTreatedInWindow = false;
759  ->GetWaveform(last->rxParams->m_txInfo.waveformId)
760  ->GetPayloadInBytes();
761  }
762 
763  NS_LOG_INFO("SatPhyRxCarrierPerWindow::GetWindowBounds - Packet "
764  << last->rxParams->m_txInfo.crdsaUniquePacketId << " from "
765  << last->sourceAddress << " is inside the window");
766  }
767 
770  return std::make_pair(m_essaPacketContainer.begin(), last);
771 }
772 
773 SatPhyRxCarrierPerWindow::packetList_t::iterator
775  const std::pair<SatPhyRxCarrierPerWindow::packetList_t::iterator,
776  SatPhyRxCarrierPerWindow::packetList_t::iterator> windowBounds)
777 {
778  NS_LOG_FUNCTION(this);
779  NS_LOG_INFO("SatPhyRxCarrierPerWindow::GetHighestSnirPacket");
780 
781  SatPhyRxCarrierPerWindow::packetList_t::iterator it, max = windowBounds.second;
782  for (it = windowBounds.first; it != windowBounds.second; it++)
783  {
784  if (it->hasBeenDecoded || !(it->hasBeenUpdated) || !(it->isInsideWindow))
785  {
786  continue;
787  }
789  if ((max == windowBounds.second) || (it->meanSinr > max->meanSinr))
790  {
791  max = it;
792  }
793  }
794  return max;
795 }
796 
797 bool
800 {
801  NS_LOG_FUNCTION(this);
802 
803  return (packet.preambleMeanSinr >= m_detectionThreshold);
804 }
805 
806 void
809 {
810  NS_LOG_FUNCTION(this);
811 
812  NS_LOG_INFO("SatPhyRxCarrierPerWindow::AddEssaPacket - Add packet "
813  << essaPacketParams.rxParams->m_txInfo.crdsaUniquePacketId << " from "
814  << essaPacketParams.sourceAddress
815  << " Arrival Time: " << essaPacketParams.arrivalTime.GetSeconds()
816  << " Duration: " << essaPacketParams.duration.GetSeconds());
817 
819  m_essaPacketContainer.push_back(essaPacketParams);
820 }
821 
822 void
824 {
825  NS_LOG_FUNCTION(this);
826 
828  double normalizedOfferedLoad = CalculateNormalizedOfferedRandomAccessLoad();
829 
831  SaveMeasuredRandomAccessLoad(normalizedOfferedLoad);
832 
834  double averageNormalizedOfferedLoad = CalculateAverageNormalizedOfferedRandomAccessLoad();
835 
836  NS_LOG_INFO("Average normalized offered load: " << averageNormalizedOfferedLoad);
837 
839  m_windowLoadTrace(normalizedOfferedLoad);
840 
842  {
844  GetBeamId(),
845  GetCarrierId(),
847  averageNormalizedOfferedLoad);
848  }
849 }
850 
851 double
853 {
854  NS_LOG_FUNCTION(this);
855 
856  double normalizedOfferedLoad = m_payloadBytesInWindow * SatConstVariables::BITS_PER_BYTE /
857  m_windowDuration.GetSeconds() / m_rxBandwidthHz;
858 
859  NS_LOG_INFO("Payload Bytes in Window: "
860  << m_payloadBytesInWindow << ", Window duration in seconds: "
861  << m_windowDuration.GetSeconds() << ", Bandwidth in Hz: " << m_rxBandwidthHz
862  << ", normalized offered load (bps/Hz): " << normalizedOfferedLoad);
863 
864  return normalizedOfferedLoad;
865 }
866 
867 } // namespace ns3
SatPhy::AverageNormalizedOfferedLoadCallback m_avgNormalizedOfferedLoadCallback
Average normalized offered load callback.
void DoCompositeSinrOutputTrace(double cSinr)
Function for composite SINR output tracing.
double m_rxExtNoisePowerW
External noise power system RX noise.
TracedCallback< double, const Address & > m_linkSinrTrace
A callback for link specific SINR in dB.
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.
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).
bool CheckAgainstLinkResults(double cSinr, Ptr< SatSignalParameters > rxParams)
Function for checking the SINR against the link results.
double CalculateCompositeSinr(double sinr1, double sinr2)
Function for calculating the composite SINR.
const bool m_randomAccessEnabled
Is random access enabled for this carrier.
Ptr< SatInterferenceElimination > GetInterferenceEliminationModel()
Get pointer to the current interference elimination model.
SatEnums::RegenerationMode_t m_linkRegenerationMode
Link regeneration mode.
Ptr< SatWaveformConf > GetWaveformConf()
Get pointer to the waveform configuration.
Ptr< SatLinkResults > GetLinkResults()
Get pointer to the link results given by the carrier creation configuration.
uint32_t GetSatId()
Get ID the ID of the satellite this carrier is attached to.
double m_rxBandwidthHz
RX Bandwidth in Hz.
Mac48Address GetOwnAddress()
Get the MAC address of the carrier.
Inherited the base functionality of SatPhyRxCarriers for ground station nodes.
uint8_t GetRandomAccessAllocationChannelId() const
Function for getting the random access allocation channel ID.
virtual void DoDispose()
Dispose implementation.
void SaveMeasuredRandomAccessLoad(double measuredRandomAccessLoad)
Function for saving the measured random access load.
bool IsRandomAccessDynamicLoadControlEnabled() const
Check if random access dynamic load control is enabled.
double CalculateAverageNormalizedOfferedRandomAccessLoad()
Function for calculating the average normalized offered random access load.
bool m_windowEndSchedulingInitialized
Has the window end scheduling been initialized.
void BeginEndScheduling()
Function for initializing the window end scheduling.
uint32_t m_payloadBytesInWindow
The number of payload bytes in the window.
void CleanOldPackets(const Time windowStartTime)
Remove old packets from packet container.
Time m_windowDuration
The duration of the sliding window.
void CalculatePacketInterferenceVectors(SatPhyRxCarrierPerWindow::essaPacketRxParams_s &packet)
Calculate gamma and Interference vectors for a single packet.
void AddEssaPacket(SatPhyRxCarrierPerWindow::essaPacketRxParams_s essaPacketParams)
Function for storing the received E-SSA packets.
double GetEffectiveSnir(const SatPhyRxCarrierPerWindow::essaPacketRxParams_s &packet)
Get the effective SNIR of the packet using the Mutual Information function.
virtual void ReceiveSlot(SatPhyRxCarrier::rxParams_s packetRxParams, const uint32_t nPackets)
Receive a slot.
double CalculateNormalizedOfferedRandomAccessLoad()
Function for calculating the normalized offered random access load.
static TypeId GetTypeId(void)
Get the TypeId of the class.
Time m_windowDelay
The delay before processing a sliding window.
void DoWindowEnd()
Function called when a window ends.
TracedCallback< uint32_t, const Address &, bool > m_essaRxErrorTrace
EssaRxError trace source.
Time m_firstWindow
The time of the first window.
void MeasureRandomAccessLoad()
Function for measuring the random access load.
std::pair< double, double > GetNormalizedPacketInterferenceTime(const SatPhyRxCarrierPerWindow::essaPacketRxParams_s &packet, const SatPhyRxCarrierPerWindow::essaPacketRxParams_s &interferingPacket)
Get the normalized start and end time between two interfering packets.
SatPhyRxCarrierPerWindow(uint32_t carrierId, Ptr< SatPhyRxCarrierConf > carrierConf, Ptr< SatWaveformConf > waveformConf, bool randomAccessEnabled)
Constructor.
bool PacketCanBeDetected(const SatPhyRxCarrierPerWindow::essaPacketRxParams_s &packet)
Function for processing a window.
double m_detectionThreshold
SNIR detection threshold for a packet (in magnitude)
virtual void DoDispose()
Dispose implementation.
void EliminatePreviousInterferences(SatPhyRxCarrierPerWindow::essaPacketRxParams_s &packet)
Calculate gamma and Interference vectors for a single packet.
std::pair< packetList_t::iterator, packetList_t::iterator > GetWindowBounds(Time startTime, Time endTime)
Get a pair of iterators, pointing to the first element in the window, and to the first after the wind...
void DoSic(packetList_t::iterator processedPacket, std::pair< packetList_t::iterator, packetList_t::iterator > windowBounds)
Perform SIC for a given decoded packet.
Time m_windowStep
The step of the sliding window.
packetList_t m_essaPacketContainer
ESSA packet container.
uint32_t m_spreadingFactor
The spreading factor of packets.
packetList_t::iterator GetHighestSnirPacket(const std::pair< packetList_t::iterator, packetList_t::iterator > windowBounds)
Get the packet with the highst SNIR on the list.
uint32_t m_windowSicIterations
The number of SIC iterations performed on each window.
TracedCallback< double > m_windowLoadTrace
WindowLoad trace source.
TracedCallback< uint32_t, const Address &, bool > m_essaRxCollisionTrace
EssaRxError trace source.
void ProcessWindow(Time startTime, Time endTime)
Function for processing a window.
std::vector< Ptr< Packet > > PacketsInBurst_t
Buffer for transmissions.
static double ScalarProduct(const std::vector< std::pair< double, double >> &vector)
Scalar product.
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.
Struct for storing the E-SSA packet specific Rx parameters.