satellite-request-manager.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013 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.com>
21  */
22 
24 
26 #include "satellite-enums.h"
27 #include "satellite-utils.h"
28 
29 #include <ns3/boolean.h>
30 #include <ns3/double.h>
31 #include <ns3/enum.h>
32 #include <ns3/log.h>
33 #include <ns3/nstime.h>
34 #include <ns3/simulator.h>
35 
36 #include <cmath>
37 
38 NS_LOG_COMPONENT_DEFINE("SatRequestManager");
39 
40 namespace ns3
41 {
42 
43 NS_OBJECT_ENSURE_REGISTERED(SatRequestManager);
44 
45 const uint32_t SatRequestManager::m_rbdcScalingFactors[4] = {1, 4, 16, 64};
46 const uint32_t SatRequestManager::m_vbdcScalingFactors[4] = {1, 8, 64, 512};
47 
49  : m_gwAddress(),
50  m_satAddress(),
51  m_lastCno(NAN),
52  m_llsConf(),
53  m_evaluationInterval(Seconds(0.1)),
54  m_cnoReportInterval(Seconds(0.0)),
55  m_gainValueK(1.0),
56  m_rttEstimate(MilliSeconds(560)),
57  m_overEstimationFactor(1.1),
58  m_enableOnDemandEvaluation(false),
59  m_pendingRbdcRequestsKbps(),
60  m_pendingVbdcBytes(),
61  m_previousEvaluationTime(),
62  m_lastVbdcCrSent(Seconds(0)),
63  m_superFrameDuration(Seconds(0)),
64  m_forcedAvbdcUpdate(false),
65  m_numValues(256),
66  m_rbdcCapacityRequestAlgorithm(SatEnums::CR_RBDC_LEGACY),
67  m_vbdcCapacityRequestAlgorithm(SatEnums::CR_VBDC_LEGACY),
68  m_headerOffsetVbcd(1.0)
69 {
70  NS_LOG_FUNCTION(this);
71 }
72 
74 {
75 }
76 
77 void
78 SatRequestManager::Initialize(Ptr<SatLowerLayerServiceConf> llsConf, Time superFrameDuration)
79 {
80  NS_LOG_FUNCTION(this << superFrameDuration.GetSeconds());
81 
82  m_llsConf = llsConf;
83 
85  std::vector<std::deque<std::pair<Time, uint32_t>>>(m_llsConf->GetDaServiceCount(),
86  std::deque<std::pair<Time, uint32_t>>());
87  m_pendingVbdcBytes = std::vector<uint32_t>(m_llsConf->GetDaServiceCount(), 0);
88  m_assignedDaResourcesBytes = std::vector<uint32_t>(m_llsConf->GetDaServiceCount(), 0);
89  m_previousEvaluationTime = std::vector<Time>(m_llsConf->GetDaServiceCount(), Seconds(0.0));
90 
91  // Superframe duration
92  m_superFrameDuration = superFrameDuration;
93 
94  // Start the request manager evaluation cycle
95  Simulator::ScheduleWithContext(m_nodeInfo->GetNodeId(),
98  this);
99 
100  // Start the C/N0 report cycle
102  Simulator::Schedule(m_cnoReportInterval, &SatRequestManager::SendCnoReport, this);
103 }
104 
105 TypeId
107 {
108  static TypeId tid =
109  TypeId("ns3::SatRequestManager")
110  .SetParent<Object>()
111  .AddConstructor<SatRequestManager>()
112  .AddAttribute("EvaluationInterval",
113  "Evaluation interval time",
114  TimeValue(Seconds(0.1)),
115  MakeTimeAccessor(&SatRequestManager::m_evaluationInterval),
116  MakeTimeChecker())
117  .AddAttribute("CnoReportInterval",
118  "C/NO report interval time",
119  TimeValue(Seconds(1.1)),
120  MakeTimeAccessor(&SatRequestManager::m_cnoReportInterval),
121  MakeTimeChecker())
122  .AddAttribute("RttEstimate",
123  "Round trip time estimate for request manager",
124  TimeValue(MilliSeconds(560)),
125  MakeTimeAccessor(&SatRequestManager::m_rttEstimate),
126  MakeTimeChecker())
127  .AddAttribute("OverEstimationFactor",
128  "Over-estimation due to RLE and FPDU overhead.",
129  DoubleValue(1.1),
130  MakeDoubleAccessor(&SatRequestManager::m_overEstimationFactor),
131  MakeDoubleChecker<double_t>())
132  .AddAttribute("EnableOnDemandEvaluation",
133  "Enable on-demand resource evaluation.",
134  BooleanValue(false),
135  MakeBooleanAccessor(&SatRequestManager::m_enableOnDemandEvaluation),
136  MakeBooleanChecker())
137  .AddAttribute("GainValueK",
138  "Gain value K for RBDC calculation.",
139  DoubleValue(1.0),
140  MakeDoubleAccessor(&SatRequestManager::m_gainValueK),
141  MakeDoubleChecker<double_t>())
142  .AddAttribute("RbdcCapacityRequestAlgorithm",
143  "Algorithm to calculate RBDC capacity requests.",
144  EnumValue(SatEnums::CR_RBDC_LEGACY),
146  MakeEnumChecker(SatEnums::CR_RBDC_LEGACY, "Legacy"))
147  .AddAttribute("VbdcCapacityRequestAlgorithm",
148  "Algorithm to calculate VBDC capacity requests.",
149  EnumValue(SatEnums::CR_VBDC_LEGACY),
151  MakeEnumChecker(SatEnums::CR_VBDC_LEGACY, "Legacy"))
152  .AddTraceSource("CrTrace",
153  "Capacity request trace",
154  MakeTraceSourceAccessor(&SatRequestManager::m_crTrace),
155  "ns3::SatRequestManager::CapacityRequestTraceCallback")
156  .AddTraceSource("CrTraceLog",
157  "Capacity request trace log",
158  MakeTraceSourceAccessor(&SatRequestManager::m_crTraceLog),
159  "ns3::SatRequestManager::CapacityRequestTraceLogCallback")
160  .AddTraceSource("RbdcTrace",
161  "Trace for all sent RBDC capacity requests.",
162  MakeTraceSourceAccessor(&SatRequestManager::m_rbdcTrace),
163  "ns3::SatRequestManager::RbdcTraceCallback")
164  .AddTraceSource("VbdcTrace",
165  "Trace for all sent VBDC capacity requests.",
166  MakeTraceSourceAccessor(&SatRequestManager::m_vbdcTrace),
167  "ns3::SatRequestManager::VbdcTraceCallback")
168  .AddTraceSource("AvbdcTrace",
169  "Trace for all sent AVBDC capacity requests.",
170  MakeTraceSourceAccessor(&SatRequestManager::m_aVbdcTrace),
171  "ns3::SatRequestManager::AvbdcTraceCallback");
172  return tid;
173 }
174 
175 TypeId
177 {
178  NS_LOG_FUNCTION(this);
179 
180  return GetTypeId();
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION(this);
187 
188  for (CallbackContainer_t::iterator it = m_queueCallbacks.begin(); it != m_queueCallbacks.end();
189  ++it)
190  {
191  it->second.Nullify();
192  }
193  m_queueCallbacks.clear();
194 
195  m_ctrlCallback.Nullify();
196 
197  m_ctrlMsgTxPossibleCallback.Nullify();
199 
200  m_llsConf = NULL;
201 
202  Object::DoDispose();
203 }
204 
205 void
207 {
208  NS_LOG_FUNCTION(this << event << (uint32_t)(rcIndex));
209 
210  if (event == SatQueue::FIRST_BUFFERED_PKT)
211  {
212  NS_LOG_INFO("FIRST_BUFFERED_PKT event received from queue: " << (uint32_t)(rcIndex));
213 
215  {
216  NS_LOG_INFO("Do on-demand CR evaluation for RC index: " << (uint32_t)(rcIndex));
217  DoEvaluation();
218  }
219  }
220  // Other queue events not handled here
221 }
222 
223 void
225 {
226  NS_LOG_FUNCTION(this);
227 
228  DoEvaluation();
229 
230  // Schedule next evaluation interval
232 }
233 
234 void
236 {
237  NS_LOG_FUNCTION(this);
238 
239  NS_LOG_INFO("---Start request manager evaluation---");
240 
241  // Check whether the ctrl msg transmission is possible
242  bool ctrlMsgTxPossible = m_ctrlMsgTxPossibleCallback();
243 
244  // The request manager evaluation is not done, if there is no
245  // possibility to send the CR. Instead, we just we wait for the next
246  // evaluation interval.
247  if (ctrlMsgTxPossible)
248  {
249  // Update the VBDC counters based on received TBTP
250  // resources
252 
253  // Check whether we should update the VBDC request
254  // with AVBDC.
256 
257  Ptr<SatCrMessage> crMsg = CreateObject<SatCrMessage>();
258 
259  // Go through the RC indices
260  for (uint8_t rc = 0; rc < m_llsConf->GetDaServiceCount(); ++rc)
261  {
262  if (m_queueCallbacks.find(rc) != m_queueCallbacks.end())
263  {
264  // Get statistics for LLC/SatQueue
265  struct SatQueue::QueueStats_t stats = m_queueCallbacks.at(rc)(true);
266 
267  NS_LOG_INFO("Evaluating the needs for RC: " << (uint32_t)(rc));
268  NS_LOG_INFO("RC: " << (uint32_t)(rc)
269  << " incoming rate: " << stats.m_incomingRateKbps << " kbps");
270  NS_LOG_INFO("RC: " << (uint32_t)(rc)
271  << " outgoing rate: " << stats.m_outgoingRateKbps << " kbps");
272  NS_LOG_INFO("RC: " << (uint32_t)(rc) << " volume in: " << stats.m_volumeInBytes
273  << " bytes");
274  NS_LOG_INFO("RC: " << (uint32_t)(rc) << " volume out: " << stats.m_volumeOutBytes
275  << " bytes");
276  NS_LOG_INFO("RC: " << (uint32_t)(rc)
277  << " total queue size: " << stats.m_queueSizeBytes << " bytes");
278 
279  // RBDC only
280  if (m_llsConf->GetDaRbdcAllowed(rc) && !m_llsConf->GetDaVolumeAllowed(rc))
281  {
282  NS_LOG_INFO("Evaluating RBDC needs for RC: " << (uint32_t)(rc));
283  uint32_t rbdcRateKbps = DoRbdc(rc, stats);
284 
285  NS_LOG_INFO("Requested RBDC rate for RC: " << (uint32_t)(rc) << " is "
286  << rbdcRateKbps << " kbps");
287 
288  if (rbdcRateKbps > 0)
289  {
290  // Add control element only if UT needs some rate
291  crMsg->AddControlElement(rc, SatEnums::DA_RBDC, rbdcRateKbps);
292 
293  std::stringstream ss;
294  ss << Simulator::Now().GetSeconds() << ", " << m_nodeInfo->GetNodeId()
295  << ", " << static_cast<uint32_t>(rc) << ", "
297  << rbdcRateKbps << ", " << stats.m_queueSizeBytes;
298  m_crTraceLog(ss.str());
299  m_rbdcTrace(rbdcRateKbps);
300  }
301  }
302 
303  // VBDC only
304  else if (m_llsConf->GetDaVolumeAllowed(rc) && !m_llsConf->GetDaRbdcAllowed(rc))
305  {
306  NS_LOG_INFO("Evaluation VBDC for RC: " << (uint32_t)(rc));
307 
308  uint32_t vbdcBytes(0);
309 
310  SatEnums::SatCapacityAllocationCategory_t cac = DoVbdc(rc, stats, vbdcBytes);
311 
312  vbdcBytes *= m_headerOffsetVbcd;
313 
314  if (vbdcBytes > 0)
315  {
316  // Add control element only if UT needs some bytes
317  crMsg->AddControlElement(rc, cac, vbdcBytes);
318 
319  // Update the time when VBDC CR is sent
320  m_lastVbdcCrSent = Simulator::Now();
321 
322  std::stringstream ss;
323  ss << Simulator::Now().GetSeconds() << ", " << m_nodeInfo->GetNodeId()
324  << ", " << static_cast<uint32_t>(rc) << ", "
325  << SatEnums::GetCapacityAllocationCategory(cac) << ", " << vbdcBytes
326  << ", " << stats.m_queueSizeBytes;
327  m_crTraceLog(ss.str());
328 
329  if (cac == SatEnums::DA_AVBDC)
330  {
331  m_aVbdcTrace(vbdcBytes);
332  }
333  else
334  {
335  m_vbdcTrace(vbdcBytes);
336  }
337  }
338 
339  NS_LOG_INFO("Requested VBDC volume for RC: " << (uint32_t)(rc) << " is "
340  << vbdcBytes
341  << " Bytes with CAC: " << cac);
342  }
343 
344  // RBDC + VBDC
345  else if (m_llsConf->GetDaRbdcAllowed(rc) && m_llsConf->GetDaVolumeAllowed(rc))
346  {
347  NS_LOG_INFO("Evaluation RBDC+VBDC for RC: " << (uint32_t)(rc));
348 
353  NS_FATAL_ERROR(
354  "Simultaneous RBDC and VBDC for one RC is not currently supported!");
355  }
356  // No dynamic DA configured
357  else
358  {
359  NS_LOG_INFO("RBDC nor VBDC was configured for RC: " << (uint32_t)(rc));
360  }
361 
362  // Update evaluation time
363  m_previousEvaluationTime.at(rc) = Simulator::Now();
364  }
365  }
366 
367  // If CR has some valid elements
368  if (crMsg->IsNotEmpty())
369  {
370  NS_LOG_INFO("Send CR");
371 
372  SendCapacityRequest(crMsg);
373  }
374 
376  }
377  else
378  {
379  NS_LOG_INFO("No transmission possibility, thus skipping CR evaluation!");
380  }
381 
382  NS_LOG_INFO("---End request manager evaluation---");
383 }
384 
385 void
387 {
388  NS_LOG_FUNCTION(this << (uint32_t)(rcIndex) << &cb);
389  m_queueCallbacks.insert(std::make_pair(rcIndex, cb));
390 }
391 
392 void
394 {
395  NS_LOG_FUNCTION(this << &cb);
396  m_ctrlCallback = cb;
397 }
398 
399 void
401 {
402  NS_LOG_FUNCTION(this << &cb);
404 }
405 
406 void
408 {
409  NS_LOG_FUNCTION(this << &cb);
411 }
412 
413 void
414 SatRequestManager::SetGwAddress(Mac48Address address)
415 {
416  NS_LOG_FUNCTION(this << address);
417  m_gwAddress = address;
418 }
419 
420 void
421 SatRequestManager::SetNodeInfo(Ptr<SatNodeInfo> nodeInfo)
422 {
423  NS_LOG_FUNCTION(this);
424 
425  m_nodeInfo = nodeInfo;
426 }
427 
428 void
430  uint32_t beamId,
431  Address sourceMac,
432  Address /*gwId*/,
433  double cno,
434  bool isSatelliteMac)
435 {
436  NS_LOG_FUNCTION(this << satId << beamId << cno);
437 
438  NS_LOG_INFO("C/No updated to request manager: " << cno);
439 
440  if (isSatelliteMac)
441  {
442  m_lastSatelliteCno = cno;
443  m_satAddress = Mac48Address::ConvertFrom(sourceMac);
444  }
445  else
446  {
447  m_lastCno = cno;
448  }
449 }
450 
451 uint32_t
453 {
454  NS_LOG_FUNCTION(this);
455 
457  {
459  return DoRbdcLegacy(rc, stats);
460  }
461  default: {
462  NS_FATAL_ERROR("SatRequestManager::DoRbdc - Invalid RBDC algorithm!");
463  }
464  }
465 
466  NS_FATAL_ERROR("SatRequestManager::DoRbdc - Invalid RBDC algorithm!");
467  return 0;
468 }
469 
470 uint32_t
472 {
473  NS_LOG_FUNCTION(this << (uint32_t)(rc));
474 
475  // Duration from last evaluation time
476  Time duration = Simulator::Now() - m_previousEvaluationTime.at(rc);
477 
478  // Calculate the raw RBDC request
479  // double gainValueK = 1.0 / (2.0 * duration.GetSeconds ());
480 
481  // This round kbits
482  double inRateKbps = m_overEstimationFactor * stats.m_incomingRateKbps;
483  double thisRbdcInKbits = inRateKbps * duration.GetSeconds();
484  double previousRbdcInKbits = GetPendingRbdcSumKbps(rc) * duration.GetSeconds();
485  double queueSizeInKbits = SatConstVariables::BITS_PER_BYTE * stats.m_queueSizeBytes /
487 
488  double queueOccupancy =
489  std::max(0.0,
490  m_gainValueK * (queueSizeInKbits - thisRbdcInKbits - previousRbdcInKbits) /
491  duration.GetSeconds());
492 
493  double reqRbdcKbps = inRateKbps + queueOccupancy;
494 
495  NS_LOG_INFO("queueSizeInKbits: " << queueSizeInKbits << " thisRbdcInKbits: " << thisRbdcInKbits
496  << " previousRbdcInKbits " << previousRbdcInKbits);
497  NS_LOG_INFO("gainValueK: " << m_gainValueK);
498  NS_LOG_INFO("In rate: " << inRateKbps << " queueOccupancy: " << queueOccupancy);
499 
500  // If CRA enabled, substract the CRA bitrate from the calculated RBDC bitrate
501  if (m_llsConf->GetDaConstantAssignmentProvided(rc))
502  {
503  // If CRA is sufficient, no RBDC needed
504  if (reqRbdcKbps <= m_llsConf->GetDaConstantServiceRateInKbps(rc))
505  {
506  reqRbdcKbps = 0.0;
507  }
508  // Else reduce the CRA from RBDC request
509  else
510  {
511  reqRbdcKbps -= m_llsConf->GetDaConstantServiceRateInKbps(rc);
512  }
513 
514  if (m_llsConf->GetDaConstantServiceRateInKbps(rc) >
515  m_llsConf->GetDaMaximumServiceRateInKbps(rc))
516  {
517  NS_FATAL_ERROR("SatRequestManager::DoRbdcLegacy - configured CRA is bigger than "
518  "maximum RBDC for RC: "
519  << uint32_t(rc));
520  }
521 
522  // CRA + RBDC is too much
523  if ((m_llsConf->GetDaConstantServiceRateInKbps(rc) + reqRbdcKbps) >
524  m_llsConf->GetDaMaximumServiceRateInKbps(rc))
525  {
526  reqRbdcKbps = m_llsConf->GetDaMaximumServiceRateInKbps(rc) -
527  m_llsConf->GetDaConstantServiceRateInKbps(rc);
528  }
529  }
530  // CRA is disabled, but check that RBDC request is not by itself going over max service rate.
531  else if (reqRbdcKbps > m_llsConf->GetDaMaximumServiceRateInKbps(rc))
532  {
533  reqRbdcKbps = m_llsConf->GetDaMaximumServiceRateInKbps(rc);
534  }
535 
536  NS_LOG_INFO("RBDC bitrate after CRA as been taken off: " << reqRbdcKbps << " kbps");
537 
538  uint32_t crRbdcKbps = GetQuantizedRbdcValue(rc, reqRbdcKbps);
539 
540  NS_LOG_INFO("Quantized RBDC bitrate: " << crRbdcKbps << " kbps");
541 
542  UpdatePendingRbdcCounters(rc, crRbdcKbps);
543 
544  return crRbdcKbps;
545 }
546 
548 SatRequestManager::DoVbdc(uint8_t rc, const SatQueue::QueueStats_t& stats, uint32_t& rcVbdcBytes)
549 {
550  NS_LOG_FUNCTION(this);
551 
553  {
555  return DoVbdcLegacy(rc, stats, rcVbdcBytes);
556  }
557  default: {
558  NS_FATAL_ERROR("SatRequestManager::DoVbdc - Invalid VBDC algorithm!");
559  }
560  }
561 
562  NS_FATAL_ERROR("SatRequestManager::DoVbdc - Invalid VBDC algorithm!");
563  return SatEnums::DA_UNKNOWN;
564 }
565 
568  const SatQueue::QueueStats_t& stats,
569  uint32_t& rcVbdcBytes)
570 {
571  NS_LOG_FUNCTION(this << (uint32_t)(rc));
572 
573  uint32_t vbdcBytes(0);
574 
576 
577  if (m_forcedAvbdcUpdate == true)
578  {
579  cac = SatEnums::DA_AVBDC;
580  vbdcBytes = GetAvbdcBytes(rc, stats);
581  }
582  else
583  {
584  // If there is volume in, there is no need to ask for additional resources
585  if (stats.m_volumeInBytes > 0)
586  {
587  NS_LOG_INFO("VBDC volume in for RC: " << (uint32_t)(rc) << ": " << stats.m_volumeInBytes
588  << " Bytes");
589 
590  // If we assume that we have received all requested resources,
591  // send AVBDC request with total queue size.
592  if (m_pendingVbdcBytes.at(rc) == 0)
593  {
594  cac = SatEnums::DA_AVBDC;
595  vbdcBytes = GetAvbdcBytes(rc, stats);
596  }
597  else
598  {
599  cac = SatEnums::DA_VBDC;
600  vbdcBytes = GetVbdcBytes(rc, stats);
601  }
602  }
603  }
604  // Return the VBDC as referenced uint32_t
605  rcVbdcBytes = vbdcBytes;
606 
607  return cac;
608 }
609 
610 uint32_t
612 {
613  NS_LOG_FUNCTION(this << (uint32_t)(rc));
614 
615  Reset(rc);
616 
617  uint32_t craBytes(0);
618  uint32_t vbdcBytes = m_overEstimationFactor * stats.m_queueSizeBytes;
619 
620  // If CRA enabled, substract the CRA Bytes from VBDC
621  if (m_llsConf->GetDaConstantAssignmentProvided(rc))
622  {
623  NS_LOG_INFO("CRA is enabled together with VBDC for RC: " << (uint32_t)(rc));
624 
625  // Duration from last evaluation time
626  Time duration = Simulator::Now() - m_previousEvaluationTime.at(rc);
627 
628  // Calculate how much bytes would be given to this RC index with configured CRA
629  craBytes =
630  (uint32_t)((SatConstVariables::BITS_IN_KBIT *
631  m_llsConf->GetDaConstantServiceRateInKbps(rc) * duration.GetSeconds()) /
633  }
634 
635  // If there is still need for Bytes after CRA
636  if (craBytes < vbdcBytes)
637  {
638  vbdcBytes -= craBytes;
639  vbdcBytes = GetQuantizedVbdcValue(rc, vbdcBytes);
640 
641  // Update the pending counters
642  m_pendingVbdcBytes.at(rc) = vbdcBytes;
643 
644  NS_LOG_INFO("Pending VBDC bytes: " << (uint32_t)(rc) << ": " << m_pendingVbdcBytes.at(rc)
645  << " Bytes");
646  }
647  else
648  {
649  vbdcBytes = 0;
650  }
651 
652  return vbdcBytes;
653 }
654 
655 uint32_t
657 {
658  NS_LOG_FUNCTION(this << (uint32_t)(rc));
659 
660  uint32_t craBytes(0);
661  uint32_t vbdcBytes = m_overEstimationFactor * stats.m_volumeInBytes;
662 
663  // If CRA enabled, substract the CRA Bytes from VBDC
664  if (m_llsConf->GetDaConstantAssignmentProvided(rc))
665  {
666  NS_LOG_INFO("CRA is enabled together with VBDC for RC: " << (uint32_t)(rc));
667 
668  // Duration from last evaluation time
669  Time duration = Simulator::Now() - m_previousEvaluationTime.at(rc);
670 
671  // Calculate how much bytes would be given to this RC index with configured CRA
672  craBytes =
673  (uint32_t)((SatConstVariables::BITS_IN_KBIT *
674  m_llsConf->GetDaConstantServiceRateInKbps(rc) * duration.GetSeconds()) /
676  }
677 
678  // If there is still need for Bytes after CRA
679  if (craBytes < vbdcBytes)
680  {
681  vbdcBytes -= craBytes;
682 
683  NS_LOG_INFO("VBDC volume after CRA for RC: " << (uint32_t)(rc) << ": " << vbdcBytes
684  << " Bytes");
685 
686  vbdcBytes = GetQuantizedVbdcValue(rc, vbdcBytes);
687  m_pendingVbdcBytes.at(rc) = m_pendingVbdcBytes.at(rc) + vbdcBytes;
688 
689  NS_LOG_INFO("Pending VBDC bytes: " << (uint32_t)(rc) << ": " << m_pendingVbdcBytes.at(rc)
690  << " Bytes");
691  NS_LOG_INFO("VBDC volume after pending: " << (uint32_t)(rc) << ": " << vbdcBytes
692  << " Bytes");
693  }
694  else
695  {
696  vbdcBytes = 0;
697  }
698 
699  return vbdcBytes;
700 }
701 
702 void
704 {
705  NS_LOG_FUNCTION(this);
706 
707  // Volume backlog shall expire at the NCC?
708  // Last sent CR + backlog persistence duration is smaller than now
709  if ((m_lastVbdcCrSent + (m_llsConf->GetVolumeBacklogPersistence() - 1) * m_superFrameDuration) <
710  Simulator::Now())
711  {
712  // Go through all RC indeces
713  for (std::vector<uint32_t>::iterator it = m_pendingVbdcBytes.begin();
714  it != m_pendingVbdcBytes.end();
715  ++it)
716  {
717  // Check if UT is still in need for resources
718  if (*it > 0)
719  {
720  // Volume backlog is about to expire, and we still have buffered data,
721  // send forced AVBDC
722  m_forcedAvbdcUpdate = true;
723  return;
724  }
725  }
726  }
727 
728  // No need to send forced AVBDC
729  m_forcedAvbdcUpdate = false;
730  return;
731 }
732 
733 uint32_t
735 {
736  NS_LOG_FUNCTION(this << (uint32_t)(rc));
737 
739 
740  uint32_t value(0);
741  std::deque<std::pair<Time, uint32_t>> cont = m_pendingRbdcRequestsKbps.at(rc);
742 
743  for (std::deque<std::pair<Time, uint32_t>>::const_iterator it = cont.begin(); it != cont.end();
744  ++it)
745  {
746  // Add the kbps
747  value += (*it).second;
748  }
749 
750  NS_LOG_INFO("Pending RBDC sum for RC: " << (uint32_t)(rc) << " is " << value);
751 
752  return value;
753 }
754 
755 void
757 {
758  NS_LOG_FUNCTION(this << (uint32_t)(rc) << kbps);
759 
760  if (kbps > 0)
761  {
762  Time now = Simulator::Now();
763  std::pair<Time, uint32_t> item = std::make_pair(now, kbps);
764  m_pendingRbdcRequestsKbps.at(rc).push_back(item);
765  }
766 }
767 
768 void
770 {
771  NS_LOG_FUNCTION(this << (uint32_t)(rc));
772 
773  std::deque<std::pair<Time, uint32_t>>& cont = m_pendingRbdcRequestsKbps.at(rc);
774  std::deque<std::pair<Time, uint32_t>>::const_iterator it = cont.begin();
775 
776  while (it != cont.end())
777  {
778  if ((*it).first < (Simulator::Now() - m_rttEstimate))
779  {
780  cont.pop_front();
781  it = cont.begin();
782  }
783  else
784  {
785  break;
786  }
787  }
788 }
789 
790 void
792 {
793  NS_LOG_FUNCTION(this);
794 
795  for (uint8_t rc = 0; rc < m_llsConf->GetDaServiceCount(); rc++)
796  {
798  }
799 }
800 
801 void
803 {
804  NS_LOG_FUNCTION(this << (uint32_t)(rc));
805 
806  /*
807  * m_pendingVbdcBytes is updated with requested bytes and reduce by allocated
808  * bytes via TBTP. This information comes from UT MAC.
809  * m_assignedDaResources holds the amount of resources allocated during the previous
810  * superframe.
811  */
812 
814  {
816  m_assignedDaResourcesBytes.at(rc) = 0;
817  }
818  else
819  {
820  m_pendingVbdcBytes.at(rc) = 0;
821  m_assignedDaResourcesBytes.at(rc) = 0;
822  }
823 }
824 
825 void
827 {
828  NS_LOG_FUNCTION(this);
829 
830  // Cancel the C/No report event
831  m_cnoReportEvent.Cancel();
832 
833  if (!m_ctrlCallback.IsNull())
834  {
835  NS_LOG_INFO("Send C/N0 report to GW: " << m_gwAddress);
836 
837  m_crTrace(Simulator::Now(), m_nodeInfo->GetMacAddress(), crMsg);
838 
839  crMsg->SetCnoEstimate(m_lastCno);
840  m_ctrlCallback(crMsg, m_gwAddress);
841 
842  m_lastCno = NAN;
843  }
844  else
845  {
846  NS_FATAL_ERROR("Unable to send capacity request, since the Ctrl callback is NULL!");
847  }
848 
849  // Re-schedule the C/No report event
851  Simulator::Schedule(m_cnoReportInterval, &SatRequestManager::SendCnoReport, this);
852 }
853 
854 void
856 {
857  NS_LOG_FUNCTION(this);
858 
859  if (!m_ctrlCallback.IsNull())
860  {
861  // Check if we have the possiblity to send a ctrl msg
862  bool ctrlMsgTxPossible = m_ctrlMsgTxPossibleCallback();
863 
864  if (ctrlMsgTxPossible && m_lastCno != NAN)
865  {
866  NS_LOG_INFO("Send C/No report to GW: " << m_gwAddress);
867 
868  Ptr<SatCnoReportMessage> cnoReport = CreateObject<SatCnoReportMessage>();
869 
870  cnoReport->SetCnoEstimate(m_lastCno);
871  m_ctrlCallback(cnoReport, m_gwAddress);
872 
873  m_lastCno = NAN;
874  }
875 
876  if (ctrlMsgTxPossible && m_lastSatelliteCno != NAN)
877  {
878  NS_LOG_INFO("Send C/No report to SAT user: " << m_satAddress);
879  Ptr<SatCnoReportMessage> cnoReport = CreateObject<SatCnoReportMessage>();
880 
881  cnoReport->SetCnoEstimate(m_lastSatelliteCno);
882  m_ctrlCallback(cnoReport, m_satAddress);
883 
884  m_lastSatelliteCno = NAN;
885  }
886  }
887 
889  Simulator::Schedule(m_cnoReportInterval, &SatRequestManager::SendCnoReport, this);
890 }
891 
892 void
894 {
895  NS_LOG_FUNCTION(this << beamId);
896 
897  // Check if we have the possiblity to send a ctrl msg
898  if (!m_ctrlCallback.IsNull() && m_ctrlMsgTxPossibleCallback())
899  {
900  NS_LOG_INFO("Send handover recommendation to GW: " << m_gwAddress);
901 
902  Ptr<SatHandoverRecommendationMessage> hoRecommendation =
903  CreateObject<SatHandoverRecommendationMessage>();
904  hoRecommendation->SetRecommendedBeamId(beamId);
905 
906  m_ctrlCallback(hoRecommendation, m_gwAddress);
907  }
908 }
909 
910 void
912 {
913  NS_LOG_FUNCTION(this);
914 
915  // Check if we have the possiblity to send a logon msg
916  // TODO add new callback
917  if (!m_ctrlCallback.IsNull() && m_logonMsgTxPossibleCallback())
918  {
919  NS_LOG_INFO("Send logon message to GW: " << m_gwAddress);
920 
921  Ptr<SatLogonMessage> logonMessage = CreateObject<SatLogonMessage>();
922  m_ctrlCallback(logonMessage, m_gwAddress);
923  }
924 }
925 
926 void
928 {
929  m_headerOffsetVbcd = headerOffsetVbcd;
930 }
931 
932 void
933 SatRequestManager::AssignedDaResources(uint8_t rcIndex, uint32_t bytes)
934 {
935  NS_LOG_FUNCTION(this << (uint32_t)(rcIndex) << bytes);
936 
937  NS_LOG_INFO("TBTP resources assigned for RC: " << (uint32_t)(rcIndex) << " bytes: " << bytes);
938 
939  m_assignedDaResourcesBytes.at(rcIndex) = m_assignedDaResourcesBytes.at(rcIndex) + bytes;
940 }
941 
942 void
944 {
945  NS_LOG_FUNCTION(this);
946 
947  for (uint32_t i = 0; i < m_llsConf->GetDaServiceCount(); ++i)
948  {
949  m_assignedDaResourcesBytes.at(i) = 0;
950  }
951 }
952 
953 void
955 {
956  NS_LOG_FUNCTION(this << (uint32_t)(rc));
957 
958  m_assignedDaResourcesBytes.at(rc) = 0;
959  m_pendingVbdcBytes.at(rc) = 0;
960 }
961 
962 uint16_t
963 SatRequestManager::GetQuantizedRbdcValue(uint8_t index, uint16_t reqRbdcKbps) const
964 {
965  NS_LOG_FUNCTION(this << (uint32_t)(index) << reqRbdcKbps);
966 
967  uint32_t maxRbdc = m_llsConf->GetDaMaximumServiceRateInKbps(index);
968  uint32_t quantValue(0);
969 
970  // Maximum configured RBDC rate
971  if (reqRbdcKbps > maxRbdc)
972  {
973  return maxRbdc;
974  }
975 
976  // Else quantize based on the predefined scaling factors from the specification
977  for (uint32_t i = 0; i < 4; i++)
978  {
979  // If the value can be represented with this scaling value
980  if (reqRbdcKbps <= m_rbdcScalingFactors[i] * m_numValues)
981  {
982  quantValue = (uint16_t)(ceil(reqRbdcKbps / (double)(m_rbdcScalingFactors[i])) *
984  return quantValue;
985  }
986  }
987 
988  NS_FATAL_ERROR("Quantized value for RBDC not calculated!");
989 
990  return quantValue;
991 }
992 
993 uint16_t
994 SatRequestManager::GetQuantizedVbdcValue(uint8_t index, uint16_t reqVbdcBytes) const
995 {
996  NS_LOG_FUNCTION(this << (uint32_t)(index) << reqVbdcBytes);
997 
998  uint32_t maxBacklogBytes =
999  SatConstVariables::BYTES_IN_KBYTE * m_llsConf->GetDaMaximumBacklogInKbytes(index);
1000  uint32_t quantValue(0);
1001 
1002  // If maximum backlog reached
1003  if (reqVbdcBytes > maxBacklogBytes)
1004  {
1005  return maxBacklogBytes;
1006  }
1007 
1008  // Else quantize based on the predefined scaling factors from the specification
1009  for (uint32_t i = 0; i < 4; ++i)
1010  {
1011  // If the value can be represented with this scaling value
1012  if (reqVbdcBytes <= m_vbdcScalingFactors[i] * m_numValues)
1013  {
1014  quantValue = (uint16_t)(ceil(reqVbdcBytes / (double)(m_vbdcScalingFactors[i])) *
1016  return quantValue;
1017  }
1018  }
1019 
1020  NS_FATAL_ERROR("Quantized value for VBDC not calculated!");
1021 
1022  return quantValue;
1023 }
1024 
1025 } // namespace ns3
SatEnums class is for simplifying the use of enumerators in the satellite module.
SatCapacityAllocationCategory_t
Definition for different types of Capacity Request (CR) messages.
static std::string GetCapacityAllocationCategory(SatCapacityAllocationCategory_t cac)
Time m_superFrameDuration
Superframe duration used for updating the volume backlog persistence.
double m_overEstimationFactor
Over-estimation factor used for estimating a bit more resources than there are in the buffers.
SatEnums::RbdcCapacityRequestAlgorithm_t m_rbdcCapacityRequestAlgorithm
The RBDC capacity algorithm to use.
SatEnums::SatCapacityAllocationCategory_t DoVbdcLegacy(uint8_t rc, const SatQueue::QueueStats_t &stats, uint32_t &rcVbdcBytes)
Legacy algorithm to do VBDC calculation for a RC.
void Reset(uint8_t rc)
Reset RC index counters.
SendCtrlCallback m_ctrlCallback
Callback to send control messages.
PendingRbdcRequestsContainer_t m_pendingRbdcRequestsKbps
Key = RC index Value -> Key = Time when the request was sent Value -> Value = Requested bitrate or by...
void AssignedDaResources(uint8_t rcIndex, uint32_t bytes)
Sat UT MAC informs that certain amount of resources have been received in TBTP.
TracedCallback< uint32_t > m_aVbdcTrace
double m_lastSatelliteCno
The last received user link C/N0 information from lower layer in linear format.
void SetLogonMsgTxPossibleCallback(SatRequestManager::LogonMsgTxPossibleCallback cb)
Set the callback to check the possibility of sending a control message.
TracedCallback< std::string > m_crTraceLog
Trace callback used for CR tracing.
void SendLogonMessage()
Send a logon message to the gateway.
Ptr< SatLowerLayerServiceConf > m_llsConf
Lower layer services conf pointer, which holds the configurations for RCs and capacity allocation cat...
static TypeId GetTypeId(void)
inherited from Object
void ReceiveQueueEvent(SatQueue::QueueEvent_t event, uint8_t rcIndex)
Receive a queue event.
void RemoveOldEntriesFromPendingRbdcContainer(uint8_t rc)
Clean-up the pending RBDC container from old samples.
void Initialize(Ptr< SatLowerLayerServiceConf > llsConf, Time superFrameDuration)
Mac48Address m_gwAddress
GW address.
uint32_t GetVbdcBytes(uint8_t rc, const SatQueue::QueueStats_t &stats)
Calculate the needed VBDC bytes for a RC.
LogonMsgTxPossibleCallback m_logonMsgTxPossibleCallback
Callback to check from MAC if a logon msg may be transmitted in the near future.
uint16_t GetQuantizedRbdcValue(uint8_t index, uint16_t reqRbdcKbps) const
The RBDC value is signalled with 8 bits, which means that to be able to signal larger than 256 values...
void UpdatePendingRbdcCounters(uint8_t rc, uint32_t kbps)
Update the pending RBDC counters with new request information.
Callback< SatQueue::QueueStats_t, bool > QueueCallback
Callback to fetch queue statistics.
SatEnums::VbdcCapacityRequestAlgorithm_t m_vbdcCapacityRequestAlgorithm
The VBDC capacity algorithm to use.
void UpdatePendingVbdcCounters()
Update pending VBDC counters for all RCs.
Ptr< SatNodeInfo > m_nodeInfo
Node information.
virtual ~SatRequestManager()
Destructor for SatRequestManager.
uint32_t GetPendingRbdcSumKbps(uint8_t rc)
Calculate the pending RBDC requests related to a specific RC.
Callback< bool > CtrlMsgTxPossibleCallback
Callback to check whether control msg transmission is possible.
void DoPeriodicalEvaluation()
Periodically check the buffer status and whether a new CR is needed to be sent.
void SetCtrlMsgTxPossibleCallback(SatRequestManager::CtrlMsgTxPossibleCallback cb)
Set the callback to check the possibility of sending a control message.
SatEnums::SatCapacityAllocationCategory_t DoVbdc(uint8_t rc, const SatQueue::QueueStats_t &stats, uint32_t &rcVbdcBytes)
Do VBDC calculation for a RC.
static const uint32_t m_rbdcScalingFactors[4]
std::vector< uint32_t > m_pendingVbdcBytes
Pending VBDC counter for each RC index.
Mac48Address m_satAddress
SAT address.
void SetNodeInfo(Ptr< SatNodeInfo > nodeInfo)
Set the node info of this UT.
void SendHandoverRecommendation(uint32_t beamId)
Send a handover recommendation message to the gateway.
virtual void DoDispose()
Dispose of this class instance.
TracedCallback< uint32_t > m_rbdcTrace
Traced callbacks for all sent RBDC and VBDC capacity requests.
void SendCnoReport()
Send the C/N0 report message via txCallback to SatNetDevice.
void ResetAssignedResources()
Reset the assigned resources counter.
uint32_t GetAvbdcBytes(uint8_t rc, const SatQueue::QueueStats_t &stats)
Calculate the needed AVBDC bytes for a RC.
uint16_t GetQuantizedVbdcValue(uint8_t index, uint16_t reqVbdcBytes) const
The RBDC value is signalled with 8 bits, which means that to be able to signal larger than 256 values...
double m_gainValueK
Gain value K for the RBDC calculation.
Callback< bool, Ptr< SatControlMessage >, const Address & > SendCtrlCallback
Control message sending callback.
void DoEvaluation()
Do evaluation of the buffer status and decide whether or not to send CRs.
uint32_t DoRbdcLegacy(uint8_t rc, const SatQueue::QueueStats_t &stats)
Legacy algorithm to do RBDC calculation for a RC.
void AddQueueCallback(uint8_t rcIndex, SatRequestManager::QueueCallback cb)
Add a callback to fetch queue statistics.
EventId m_cnoReportEvent
Event id for the C/NO report.
uint32_t DoRbdc(uint8_t rc, const SatQueue::QueueStats_t &stats)
Do RBDC calculation for a RC.
static const uint32_t m_vbdcScalingFactors[4]
Time m_rttEstimate
Round trip time estimate.
TracedCallback< Time, Mac48Address, Ptr< SatCrMessage > > m_crTrace
Trace callback used for CR tracing.
TracedCallback< uint32_t > m_vbdcTrace
std::vector< uint32_t > m_assignedDaResourcesBytes
Dedicated assignments received within the previous superframe.
Time m_lastVbdcCrSent
Time when the last CR including VBDC request was sent.
double m_lastCno
The last received on E2E C/N0 information from lower layer in linear format.
Time m_cnoReportInterval
Interval to send C/N0 report.
void SetGwAddress(Mac48Address address)
Set the GW address needed for CR transmission.
bool m_forcedAvbdcUpdate
Flag indicating that UT should send a forced AVBDC request, since the volume backlog persistence shal...
void SendCapacityRequest(Ptr< SatCrMessage > crMsg)
Send the capacity request control msg via txCallback to SatNetDevice.
Time m_evaluationInterval
Interval to do the periodical CR evaluation.
double m_headerOffsetVbcd
Additional VBDC to add to take into account E2E header in regenerative LINK or NETWORK,...
bool m_enableOnDemandEvaluation
Enable on demand / ad hoc CR evaluation.
void CheckForVolumeBacklogPersistence()
Check whether VBDC volume backlog persistence shall expire and whether UT should update request by AV...
void SetHeaderOffsetVbdc(double headerOffsetVbcd)
Update the value of header offset.
virtual TypeId GetInstanceTypeId(void) const
Get the type ID of instance.
CtrlMsgTxPossibleCallback m_ctrlMsgTxPossibleCallback
Callback to check from MAC if a control msg may be transmitted in the near future.
SatRequestManager()
Default constructor.
void CnoUpdated(uint32_t satId, uint32_t beamId, Address sourceMac, Address gwId, double cno, bool isSatelliteMac)
Update C/N0 information from lower layer.
void SetCtrlMsgCallback(SatRequestManager::SendCtrlCallback cb)
Set the control message sending callback.
CallbackContainer_t m_queueCallbacks
The queue enque/deque rate getter callback.
std::vector< Time > m_previousEvaluationTime
Time when CR evaluation was previously done.
Callback< bool > LogonMsgTxPossibleCallback
Callback to check whether logon msg transmission is possible.
constexpr uint32_t BITS_IN_KBIT
Number of bits consisting a kilobit.
constexpr uint32_t BITS_PER_BYTE
Number of bits in a byte.
constexpr uint32_t BYTES_IN_KBYTE
Number of bytes consisting a kilobyte.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
QueueStats_t definition for passing queue related statistics to any interested modules.