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 #include <vector>
40 
41 NS_LOG_COMPONENT_DEFINE("SatPhyRxCarrierPerWindow");
42 
43 namespace ns3
44 {
45 
46 NS_OBJECT_ENSURE_REGISTERED(SatPhyRxCarrierPerWindow);
47 
49  Ptr<SatPhyRxCarrierConf> carrierConf,
50  Ptr<SatWaveformConf> waveformConf,
51  bool randomAccessEnabled)
52  : SatPhyRxCarrierPerSlot(carrierId, carrierConf, waveformConf, randomAccessEnabled),
53  m_windowDuration(MilliSeconds(60)),
54  m_windowStep(MilliSeconds(20)),
55  m_windowDelay(Seconds(0)),
56  m_firstWindow(Seconds(0)),
57  m_windowSicIterations(10),
58  m_spreadingFactor(0),
59  m_windowEndSchedulingInitialized(false),
60  m_detectionThreshold(0.0),
61  m_sicEnabled(true)
62 {
63  NS_LOG_FUNCTION(this);
64  NS_LOG_INFO("Constructor called with arguments " << carrierId << ", " << carrierConf << ", and "
65  << randomAccessEnabled);
66 
67  NS_ASSERT(m_randomAccessEnabled == true);
68 }
69 
70 void
72 {
73  NS_LOG_FUNCTION(this);
75  {
76  if (GetNodeInfo() == nullptr)
77  {
78  NS_FATAL_ERROR("SatPhyRxWindow::BeginWindowEndScheduling - m_nodeInfo not set");
79  }
80 
82 
85  Simulator::ScheduleWithContext(GetNodeInfo()->GetNodeId(),
88  this);
89  }
90 }
91 
93 {
94  NS_LOG_FUNCTION(this);
95 }
96 
97 TypeId
99 {
100  static TypeId tid =
101  TypeId("ns3::SatPhyRxCarrierPerWindow")
102  .SetParent<SatPhyRxCarrierPerSlot>()
103  .AddAttribute("WindowDuration",
104  "The duration of the sliding window",
105  TimeValue(MilliSeconds(60)),
107  MakeTimeChecker())
108  .AddAttribute("WindowStep",
109  "The length of the step between two window iterations",
110  TimeValue(MilliSeconds(20)),
111  MakeTimeAccessor(&SatPhyRxCarrierPerWindow::m_windowStep),
112  MakeTimeChecker())
113  .AddAttribute(
114  "WindowDelay",
115  "The delay before processing a sliding window, waiting for incomplete packets",
116  TimeValue(Seconds(0)),
117  MakeTimeAccessor(&SatPhyRxCarrierPerWindow::m_windowDelay),
118  MakeTimeChecker())
119  .AddAttribute("FirstWindow",
120  "The time at which the first window is processed",
121  TimeValue(Seconds(0)),
122  MakeTimeAccessor(&SatPhyRxCarrierPerWindow::m_firstWindow),
123  MakeTimeChecker())
124  .AddAttribute("WindowSICIterations",
125  "The number of SIC iterations performed on each window",
126  UintegerValue(10),
128  MakeUintegerChecker<uint32_t>())
129  // TODO: this shouldn't be here!! find a way to retrieve SF from SuperFrameConf,
130  // maybe store SF in waveform.
131  .AddAttribute("SpreadingFactor",
132  "The spreading factor of the packets",
133  UintegerValue(1),
134  MakeUintegerAccessor(&SatPhyRxCarrierPerWindow::m_spreadingFactor),
135  MakeUintegerChecker<uint32_t>())
136  .AddAttribute("DetectionThreshold",
137  "The SNIR Detection Threshold (in magnitude) for a packet",
138  DoubleValue(0.0),
140  MakeDoubleChecker<double>(0, std::numeric_limits<double>::max()))
141  .AddAttribute("EnableSIC",
142  "Use SIC when decoding a packet",
143  BooleanValue(true),
144  MakeBooleanAccessor(&SatPhyRxCarrierPerWindow::m_sicEnabled),
145  MakeBooleanChecker())
146  .AddTraceSource(
147  "EssaRxCollision",
148  "Received a packet through Random Access ESSA",
149  MakeTraceSourceAccessor(&SatPhyRxCarrierPerWindow::m_essaRxCollisionTrace),
150  "ns3::SatPhyRxCarrierPacketProbe::RxStatusCallback")
151  .AddTraceSource("EssaRxError",
152  "Received a packet through Random Access ESSA",
153  MakeTraceSourceAccessor(&SatPhyRxCarrierPerWindow::m_essaRxErrorTrace),
154  "ns3::SatPhyRxCarrierPacketProbe::RxStatusCallback")
155  .AddTraceSource("WindowLoad",
156  "Performed a window load measurement",
157  MakeTraceSourceAccessor(&SatPhyRxCarrierPerWindow::m_windowLoadTrace),
158  "ns3::SatPhyRxCarrierPerWindow::WindowLoadTraceCallback");
159  return tid;
160 }
161 
162 void
164 {
166 }
167 
168 void
170  const uint32_t nPackets)
171 {
172  NS_ASSERT(packetRxParams.rxParams->m_txInfo.packetType !=
174 
175  if (packetRxParams.rxParams->m_txInfo.packetType != SatEnums::PACKET_TYPE_ESSA)
176  {
177  NS_LOG_ERROR("SatPhyRxCarrierPerWindow::ReceiveSlot - Time: "
178  << Now().GetSeconds() << " - Non ESSA packet received");
179  return;
180  }
181 
182  NS_LOG_INFO("SatPhyRxCarrierPerWindow::ReceiveSlot - Time: " << Now().GetSeconds()
183  << " - ESSA packet received");
184 
186 
187  params.destAddress = packetRxParams.destAddress;
188  params.sourceAddress = packetRxParams.sourceAddress;
189  params.duration = packetRxParams.rxParams->m_duration;
190  params.arrivalTime = Now() - params.duration; // arrival time is the start of reception
191  params.rxParams = packetRxParams.rxParams;
192  params.hasBeenDecoded = false;
193  params.failedSic = false;
194  params.hasBeenUpdated = false;
195  params.isInsideWindow = false;
196  params.meanSinr = -1.0;
197  params.preambleMeanSinr = -1.0;
198 
199  // Calculate SINR, gamma and ifPowerPerFragment
201 
202  // Check if packet can be detected
203  if (!PacketCanBeDetected(params))
204  {
205  NS_LOG_INFO("SatPhyRxCarrierPerWindow::ReceiveSlot - Packet "
206  << params.rxParams->m_txInfo.crdsaUniquePacketId << " from "
207  << params.sourceAddress << " cannot be detected. Ignore it.");
209  m_essaRxCollisionTrace(1, // number of packets
210  params.sourceAddress, // sender address
211  1); // error flag
212  return;
213  }
214 
215  // Eliminate interference from already decoded packets
216  // WARNING: with some combinations of window size and step, it may be possible that
217  // previously decoded packets have already been cleaned.
219 
220  // Calculate SINR, gamma and ifPowerPerFragment
222 
223  AddEssaPacket(params);
224 }
225 
226 void
229 {
230  NS_LOG_FUNCTION(this);
231 
232  if (!m_sicEnabled)
233  {
234  return;
235  }
236 
237  NS_LOG_INFO("SatPhyRxCarrierPerWindow::EliminatePreviousInterferences - Eliminate "
238  "interferences from packet "
239  << packet.rxParams->m_txInfo.crdsaUniquePacketId << " from "
240  << packet.sourceAddress);
241 
242  // Get which packets that have been decoded interfere with this packet
243  packetList_t::iterator packet_it;
244  for (packet_it = m_essaPacketContainer.begin(); packet_it != m_essaPacketContainer.end();
245  packet_it++)
246  {
248  if ((packet_it->arrivalTime + packet_it->duration) <= packet.arrivalTime)
249  {
250  continue;
251  }
253  if (!(packet_it->hasBeenDecoded))
254  {
255  continue;
256  }
258  std::pair<double, double> normalizedTimes =
259  GetNormalizedPacketInterferenceTime(packet, *packet_it);
260 
261  NS_LOG_INFO("SatPhyRxCarrierPerWindow::EliminatePreviousInterferences - eliminate "
262  "interference with packet "
263  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId << " from "
264  << packet_it->sourceAddress);
266  GetInterferenceEliminationModel()->EliminateInterferences(
267  packet.rxParams,
268  packet_it->rxParams,
269  packet_it->meanSinr * m_spreadingFactor,
271  normalizedTimes.first,
272  normalizedTimes.second);
273  }
274 }
275 
276 void
279 {
280  NS_LOG_FUNCTION(this);
281  NS_LOG_INFO("SatPhyRxCarrierPerWindow::CalculatePacketInterferenceVectors - Packet "
282  << packet.rxParams->m_txInfo.crdsaUniquePacketId << " from "
283  << packet.sourceAddress);
284 
285  // TODO: should we check the interference model used ?
286  // TODO: should we check the collision model used (check against sinr, collision always drops,
287  // etc) ?
288 
289  double snr = CalculateSinr(packet.rxParams->m_rxPower_W,
290  0.0,
295 
296  double cSnr;
298  {
300  double snrSatellite = CalculateSinr(packet.rxParams->GetRxPowerInSatellite(),
301  0.0,
302  packet.rxParams->GetRxNoisePowerInSatellite(),
303  packet.rxParams->GetRxAciIfPowerInSatellite(),
304  packet.rxParams->GetRxExtNoisePowerInSatellite(),
305  packet.rxParams->GetAdditionalInterference());
306 
307  cSnr = CalculateCompositeSinr(snr, snrSatellite);
308  }
309  else
310  {
311  cSnr = snr;
312  }
313 
315  if (packet.meanSinr < 0.0)
316  {
317  SatSignalParameters::PacketsInBurst_t packets = packet.rxParams->m_packetsInBurst;
318  SatSignalParameters::PacketsInBurst_t::const_iterator i;
319  for (i = packets.begin(); i != packets.end(); i++)
320  {
321  SatUplinkInfoTag satUplinkInfoTag;
322  (*i)->RemovePacketTag(satUplinkInfoTag);
323  satUplinkInfoTag.SetSinr(snr, m_additionalInterferenceCallback());
324  (*i)->AddPacketTag(satUplinkInfoTag);
325  }
326 
327  // Update link specific SINR trace
329 
330  // Update composite SNR trace for DAMA and Slotted ALOHA packets
331  // m_sinrTrace (SatUtils::LinearToDb (cSnr), packet.sourceAddress); // Done with effective
332  // SINR
333 
334  m_linkBudgetTrace(packet.rxParams, GetOwnAddress(), packet.destAddress, 0.0, cSnr);
335 
338  {
340  }
341 
342  NS_LOG_INFO("SatPhyRxCarrierPerWindow::CalculatePacketInterferenceVectors - Received "
343  "packet SNR dB = "
344  << SatUtils::LinearToDb(cSnr));
345  }
346 
348  packet.gamma.clear();
349 
350  std::vector<std::pair<double, double>> interferencePowerPerFragment =
351  packet.rxParams->GetInterferencePowerPerFragment();
352  std::vector<std::pair<double, double>>::iterator interferencePower =
353  interferencePowerPerFragment.begin();
354  double normalizedTime = interferencePower->first, normalizedTimeInSatellite = 0.0;
361  {
362  std::vector<std::pair<double, double>> interferencePowerPerFragmentInSatellite =
363  packet.rxParams->GetInterferencePowerInSatellitePerFragment();
364  for (std::vector<std::pair<double, double>>::iterator interferencePowerInSatellite =
365  interferencePowerPerFragmentInSatellite.begin();
366  interferencePowerInSatellite != interferencePowerPerFragmentInSatellite.end();
367  interferencePowerInSatellite++)
368  {
369  normalizedTimeInSatellite += interferencePowerInSatellite->first;
372  if (normalizedTimeInSatellite > normalizedTime)
373  {
374  interferencePower++;
375  normalizedTime += interferencePower->first;
376  }
377 
380 
382  double cI = (packet.rxParams->GetRxPowerInSatellite() * packet.rxParams->m_rxPower_W) /
383  (interferencePowerInSatellite->second * packet.rxParams->m_rxPower_W +
384  interferencePower->second * packet.rxParams->GetRxPowerInSatellite());
385 
387  double gamma = 1 / (1 / cI + 1 / cSnr);
388  packet.gamma.emplace_back(interferencePowerInSatellite->first, gamma);
389  }
390  }
391  else
392  {
395 
397  double cI = (packet.rxParams->m_rxPower_W) /
398  (packet.rxParams->m_rxPower_W + interferencePower->second);
399 
401  double gamma = 1 / (1 / cI + 1 / cSnr);
402  packet.gamma.emplace_back(1, gamma);
403  }
404 
406  std::vector<std::pair<double, double>> gammaPreamble;
407  Ptr<SatWaveform> wf = GetWaveformConf()->GetWaveform(packet.rxParams->m_txInfo.waveformId);
408  normalizedTime = 0.0;
409  double normalizedPreambleTime =
410  wf->GetPreambleLengthInSymbols() /
411  wf->GetBurstLengthInSymbols(); // This asumes that preamble and burst have the same symbol
412  // rate
413  for (std::vector<std::pair<double, double>>::iterator it = packet.gamma.begin();
414  it != packet.gamma.end();
415  it++)
416  {
417  if (normalizedTime + it->first > normalizedPreambleTime)
418  {
419  gammaPreamble.emplace_back(1.0 - normalizedTime, it->second);
420  break;
421  }
422  gammaPreamble.emplace_back(it->first / normalizedPreambleTime, it->second);
423  normalizedTime += it->first;
424  }
425 
427  packet.meanSinr = SatUtils::ScalarProduct(packet.gamma);
428  packet.preambleMeanSinr = SatUtils::ScalarProduct(gammaPreamble);
429 
430  packet.hasBeenUpdated = true;
431 }
432 
433 void
435 {
436  NS_LOG_FUNCTION(this);
437  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoWindowEnd");
438 
439  // ProcessWindow (Now () - m_windowDuration, Now ());
440  Simulator::Schedule(m_windowDelay,
442  this,
443  Now() - m_windowDuration,
444  Now());
445 
446  // Advance the window (schedule DoWindowEnd for m_windowStep)
447  Simulator::Schedule(m_windowStep, &SatPhyRxCarrierPerWindow::DoWindowEnd, this);
448 }
449 
450 void
451 SatPhyRxCarrierPerWindow::ProcessWindow(Time startTime, Time endTime)
452 {
453  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoProcessWindow - Process window between "
454  << startTime.GetSeconds() << " and " << endTime.GetSeconds());
455 
457  CleanOldPackets(startTime);
458 
460  std::pair<packetList_t::iterator, packetList_t::iterator> windowBounds =
461  GetWindowBounds(startTime, endTime);
462 
463  uint32_t i = 0;
464  while (i < m_windowSicIterations)
465  {
466  while (true)
467  {
469  packetList_t::iterator packet_it = GetHighestSnirPacket(windowBounds);
470  if (packet_it == windowBounds.second)
471  {
472  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoWindowEnd - No more packets to decode");
473  break;
474  }
475  packet_it->hasBeenTreatedInWindow = true;
476 
477  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoWindowEnd - Process packet "
478  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId << " from "
479  << packet_it->sourceAddress);
481  packet_it->hasBeenUpdated = false;
483  double sinrEffective = GetEffectiveSnir(*packet_it);
484  m_sinrTrace(SatUtils::LinearToDb(sinrEffective), packet_it->sourceAddress);
486  bool phyError = CheckAgainstLinkResults(sinrEffective, packet_it->rxParams);
487  // Trace if the packet has been decoded or not
488  m_essaRxErrorTrace(1, // number of packets
489  packet_it->sourceAddress, // sender address
490  phyError); // error flag
491  if (!phyError)
492  {
493  packet_it->hasBeenDecoded = true;
495  DoSic(packet_it, windowBounds);
497  NS_LOG_WARN("received " << packet_it->sourceAddress << " "
498  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId << " "
499  << " INFO " << *(packet_it->rxParams->m_packetsInBurst[0]));
500  }
501  else
502  {
503  NS_LOG_INFO("Failed to decode packet "
504  << packet_it->sourceAddress << "-"
505  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId);
506  packet_it->failedSic = true;
507  }
508  }
509 
510  // increase iteration number
511  i++;
512  }
514  for (packetList_t::iterator packet_it = windowBounds.first; packet_it != windowBounds.second;
515  packet_it++)
516  {
518  if (!packet_it->isInsideWindow || !packet_it->hasBeenTreatedInWindow)
519  {
520  continue;
521  }
522  m_rxCallback(packet_it->rxParams, !packet_it->hasBeenDecoded);
525  }
528  {
530  }
531  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoWindowEnd - Window processing finished");
532 }
533 
534 void
536  packetList_t::iterator processedPacket,
537  std::pair<packetList_t::iterator, packetList_t::iterator> windowBounds)
538 {
539  NS_LOG_FUNCTION(this);
540 
541  if (!m_sicEnabled)
542  {
543  return;
544  }
545 
546  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoSic - eliminate interference from packet "
547  << processedPacket->rxParams->m_txInfo.crdsaUniquePacketId << " from "
548  << processedPacket->sourceAddress);
549 
551  for (packetList_t::iterator packet_it = windowBounds.first; packet_it != windowBounds.second;
552  packet_it++)
553  {
555  if (packet_it->arrivalTime >= processedPacket->arrivalTime + processedPacket->duration)
556  {
557  break;
558  }
560  if (packet_it->arrivalTime + packet_it->duration <= processedPacket->arrivalTime)
561  {
562  continue;
563  }
565  if (packet_it == processedPacket || packet_it->hasBeenDecoded)
566  {
567  continue;
568  }
569  NS_LOG_INFO("SatPhyRxCarrierPerWindow::DoSic - eliminate interference with packet "
570  << packet_it->rxParams->m_txInfo.crdsaUniquePacketId << " from "
571  << packet_it->sourceAddress);
573  std::pair<double, double> normalizedTimes =
574  GetNormalizedPacketInterferenceTime(*packet_it, *processedPacket);
576  GetInterferenceEliminationModel()->EliminateInterferences(
577  packet_it->rxParams,
578  processedPacket->rxParams,
579  processedPacket->meanSinr * m_spreadingFactor,
581  normalizedTimes.first,
582  normalizedTimes.second);
583 
585  }
586 }
587 
588 std::pair<double, double>
591  const SatPhyRxCarrierPerWindow::essaPacketRxParams_s& interferingPacket)
592 {
593  NS_LOG_FUNCTION(this);
594 
598  double startTimeA =
599  std::max(0.0,
600  1.0 - ((packet.duration.GetDouble() + packet.arrivalTime.GetDouble() -
601  interferingPacket.arrivalTime.GetDouble()) /
602  packet.duration.GetDouble()));
603  double endTimeA = std::min(
604  1.0,
605  1.0 - (packet.arrivalTime.GetDouble() - interferingPacket.arrivalTime.GetDouble()) /
606  packet.duration.GetDouble());
607  double startTimeB =
608  std::max(0.0,
609  (interferingPacket.arrivalTime.GetDouble() - packet.arrivalTime.GetDouble()) /
610  packet.duration.GetDouble());
611  double endTimeB =
612  std::min(1.0,
613  2.0 - (packet.arrivalTime.GetDouble() - interferingPacket.arrivalTime.GetDouble() +
614  packet.duration.GetDouble()) /
615  packet.duration.GetDouble());
616 
618  // some rounding errors)
619  double normalizedTime = 0.0;
620  double exactStartTime = (startTimeA == 0.0) ? 0.0 : -1.0;
621  double exactEndTime = -1.0;
622  auto ifPowerPerFragment = packet.rxParams->GetInterferencePowerInSatellitePerFragment();
623  for (std::pair<double, double>& ifPower : ifPowerPerFragment)
624  {
625  normalizedTime += ifPower.first;
626  if ((exactStartTime < 0) && (normalizedTime == startTimeA || normalizedTime == startTimeB))
627  {
628  exactStartTime = normalizedTime;
629  }
630  if ((exactEndTime < 0) && (normalizedTime == endTimeA || normalizedTime == endTimeB))
631  {
632  exactEndTime = normalizedTime;
633  }
634  }
635 
636  if ((exactStartTime < 0) || (exactEndTime < 0))
637  {
638  NS_FATAL_ERROR("Cannot find exact interference time between two packets");
639  }
640 
641  return std::make_pair(exactStartTime, exactEndTime);
642 }
643 
644 double
647 {
648  NS_LOG_FUNCTION(this);
649 
650  Ptr<SatLinkResultsRtn> satLinkResults = GetLinkResults()->GetObject<SatLinkResultsFSim>();
651  Ptr<SatMutualInformationTable> mutualInformationTable;
652  if (satLinkResults != nullptr)
653  {
654  mutualInformationTable =
656  }
657  else
658  {
659  mutualInformationTable =
660  (GetLinkResults()->GetObject<SatLinkResultsLora>())->GetMutualInformationTable();
661  }
662  double beta = mutualInformationTable->GetBeta();
663 
664  double meanMutualInformation = 0.0;
665  for (std::vector<std::pair<double, double>>::const_iterator it = packet.gamma.begin();
666  it != packet.gamma.end();
667  it++)
668  {
669  meanMutualInformation += it->first * mutualInformationTable->GetNormalizedSymbolInformation(
670  SatUtils::LinearToDb(it->second / beta));
671  }
672 
673  double effectiveSnir =
674  beta * SatUtils::DbToLinear(mutualInformationTable->GetSnirDb(meanMutualInformation));
675 
676  NS_LOG_INFO("SatPhyRxCarrierPerWindow::GetEffectiveSnir - Packet "
677  << packet.rxParams->m_txInfo.crdsaUniquePacketId << " from " << packet.sourceAddress
678  << " - Effective SNIR dB: " << SatUtils::LinearToDb(effectiveSnir));
679 
680  return effectiveSnir;
681 }
682 
683 void
684 SatPhyRxCarrierPerWindow::CleanOldPackets(const Time windowStartTime)
685 {
686  NS_LOG_FUNCTION(this);
687  NS_LOG_INFO("SatPhyRxCarrierPerWindow::CleanOldPackets");
688 
689  packetList_t::iterator it = m_essaPacketContainer.begin();
690  while (it != m_essaPacketContainer.end())
691  {
693  Time offset = it->arrivalTime - windowStartTime;
694  if (offset.IsStrictlyPositive())
695  {
696  break;
697  }
699  offset = it->arrivalTime + it->duration - windowStartTime;
700  if (!offset.IsStrictlyPositive())
701  {
702  // Only trace packets that arrived after first Window
703  if (it->arrivalTime >= m_firstWindow)
704  {
705  if (!(it->hasBeenDecoded))
706  {
707  }
708  else
709  {
710  m_daRxTrace(1, // number of packets
711  it->sourceAddress, // sender address
712  it->failedSic // error flag
713  );
714  }
715  // Trace if the packet has been decoded or not
716  m_essaRxCollisionTrace(1, // number of packets
717  it->sourceAddress, // sender address
718  !(it->hasBeenDecoded)); // error flag
719  }
720  // Delete element from list
721  NS_LOG_INFO("SatPhyRxCarrierPerWindow::CleanOldPackets - Remove packet "
722  << it->rxParams->m_txInfo.crdsaUniquePacketId << " from "
723  << it->sourceAddress);
724  it->rxParams = nullptr;
725  m_essaPacketContainer.erase(it++);
726  }
727  else
728  {
729  ++it;
730  }
731  }
732 }
733 
734 std::pair<SatPhyRxCarrierPerWindow::packetList_t::iterator,
735  SatPhyRxCarrierPerWindow::packetList_t::iterator>
736 SatPhyRxCarrierPerWindow::GetWindowBounds(Time startTime, Time endTime)
737 {
738  NS_LOG_FUNCTION(this);
739  NS_LOG_INFO("SatPhyRxCarrierPerWindow::GetWindowBounds");
740 
741  packetList_t::iterator last;
743 
744  for (last = m_essaPacketContainer.begin(); last != m_essaPacketContainer.end(); last++)
745  {
747  last->isInsideWindow = false;
749  if (last->arrivalTime > endTime)
750  {
751  break;
752  }
754  if ((last->arrivalTime >= startTime) && (last->arrivalTime + last->duration <= endTime))
755  {
756  last->isInsideWindow = true;
757  last->hasBeenTreatedInWindow = false;
760  ->GetWaveform(last->rxParams->m_txInfo.waveformId)
761  ->GetPayloadInBytes();
762  }
763 
764  NS_LOG_INFO("SatPhyRxCarrierPerWindow::GetWindowBounds - Packet "
765  << last->rxParams->m_txInfo.crdsaUniquePacketId << " from "
766  << last->sourceAddress << " is inside the window");
767  }
768 
771  return std::make_pair(m_essaPacketContainer.begin(), last);
772 }
773 
774 SatPhyRxCarrierPerWindow::packetList_t::iterator
776  const std::pair<SatPhyRxCarrierPerWindow::packetList_t::iterator,
777  SatPhyRxCarrierPerWindow::packetList_t::iterator> windowBounds)
778 {
779  NS_LOG_FUNCTION(this);
780  NS_LOG_INFO("SatPhyRxCarrierPerWindow::GetHighestSnirPacket");
781 
782  SatPhyRxCarrierPerWindow::packetList_t::iterator it, max = windowBounds.second;
783  for (it = windowBounds.first; it != windowBounds.second; it++)
784  {
785  if (it->hasBeenDecoded || !(it->hasBeenUpdated) || !(it->isInsideWindow))
786  {
787  continue;
788  }
790  if ((max == windowBounds.second) || (it->meanSinr > max->meanSinr))
791  {
792  max = it;
793  }
794  }
795  return max;
796 }
797 
798 bool
801 {
802  NS_LOG_FUNCTION(this);
803 
804  return (packet.preambleMeanSinr >= m_detectionThreshold);
805 }
806 
807 void
810 {
811  NS_LOG_FUNCTION(this);
812 
813  NS_LOG_INFO("SatPhyRxCarrierPerWindow::AddEssaPacket - Add packet "
814  << essaPacketParams.rxParams->m_txInfo.crdsaUniquePacketId << " from "
815  << essaPacketParams.sourceAddress
816  << " Arrival Time: " << essaPacketParams.arrivalTime.GetSeconds()
817  << " Duration: " << essaPacketParams.duration.GetSeconds());
818 
820  m_essaPacketContainer.push_back(essaPacketParams);
821 }
822 
823 void
825 {
826  NS_LOG_FUNCTION(this);
827 
829  double normalizedOfferedLoad = CalculateNormalizedOfferedRandomAccessLoad();
830 
832  SaveMeasuredRandomAccessLoad(normalizedOfferedLoad);
833 
835  double averageNormalizedOfferedLoad = CalculateAverageNormalizedOfferedRandomAccessLoad();
836 
837  NS_LOG_INFO("Average normalized offered load: " << averageNormalizedOfferedLoad);
838 
840  m_windowLoadTrace(normalizedOfferedLoad);
841 
843  {
845  GetBeamId(),
846  GetCarrierId(),
848  averageNormalizedOfferedLoad);
849  }
850 }
851 
852 double
854 {
855  NS_LOG_FUNCTION(this);
856 
857  double normalizedOfferedLoad = m_payloadBytesInWindow * SatConstVariables::BITS_PER_BYTE /
858  m_windowDuration.GetSeconds() / m_rxBandwidthHz;
859 
860  NS_LOG_INFO("Payload Bytes in Window: "
861  << m_payloadBytesInWindow << ", Window duration in seconds: "
862  << m_windowDuration.GetSeconds() << ", Bandwidth in Hz: " << m_rxBandwidthHz
863  << ", normalized offered load (bps/Hz): " << normalizedOfferedLoad);
864 
865  return normalizedOfferedLoad;
866 }
867 
868 } // 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.