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