satellite-ut-llc.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  *
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: Jani Puttonen <jani.puttonen@magister.fi>
19  */
20 
21 #include "satellite-ut-llc.h"
22 
24 #include "satellite-enums.h"
28 #include "satellite-node-info.h"
33 #include "satellite-utils.h"
34 
35 #include <ns3/address.h>
36 #include <ns3/log.h>
37 #include <ns3/mac48-address.h>
38 #include <ns3/packet.h>
39 #include <ns3/pointer.h>
40 #include <ns3/simulator.h>
41 
42 NS_LOG_COMPONENT_DEFINE("SatUtLlc");
43 
44 namespace ns3
45 {
46 
47 NS_OBJECT_ENSURE_REGISTERED(SatLlc);
48 
49 TypeId
51 {
52  static TypeId tid = TypeId("ns3::SatUtLlc")
53  .SetParent<SatLlc>()
54  .AddConstructor<SatUtLlc>()
55  .AddAttribute("SatRequestManager",
56  "The request manager of this UT.",
57  PointerValue(),
58  MakePointerAccessor(&SatUtLlc::GetRequestManager,
60  MakePointerChecker<SatRequestManager>());
61  return tid;
62 }
63 
65  : m_requestManager()
66 {
67  NS_LOG_FUNCTION(this);
68  NS_ASSERT(false); // this version of the constructor should not been used
69 }
70 
72  SatEnums::RegenerationMode_t returnLinkRegenerationMode)
73  : SatLlc(forwardLinkRegenerationMode, returnLinkRegenerationMode),
74  m_requestManager()
75 {
76  NS_LOG_FUNCTION(this);
77 }
78 
80 {
81  NS_LOG_FUNCTION(this);
82 }
83 
84 void
86 {
87  NS_LOG_FUNCTION(this);
88 
89  if (m_requestManager)
90  {
91  m_requestManager->DoDispose();
92  m_requestManager = 0;
93  }
94 
95  m_macQueueEventCb.Nullify();
96 
98 }
99 
100 bool
101 SatUtLlc::Enque(Ptr<Packet> packet, Address dest, uint8_t flowId)
102 {
103  NS_LOG_FUNCTION(this << packet << dest << (uint32_t)flowId);
104  NS_LOG_INFO("p=" << packet);
105  NS_LOG_INFO("dest=" << dest);
106  NS_LOG_INFO("UID is " << packet->GetUid());
107 
108  Mac48Address destMacAddress;
109  if (dest != m_satelliteAddress)
110  {
111  destMacAddress = Mac48Address::ConvertFrom(m_gwAddress);
112  }
113  else
114  {
115  destMacAddress = Mac48Address::ConvertFrom(dest);
116  }
117 
119  {
120  SatGroundStationAddressTag groundStationAddressTag =
121  SatGroundStationAddressTag(destMacAddress);
122  packet->AddPacketTag(groundStationAddressTag);
123  }
124 
125  // all multicast traffic is delivered with GW address
126  // in order to avoid supporting several encaps in UT
127  // in return link there is only one receiver (GW) for the multicast traffic for the UT
128  if (destMacAddress.IsGroup())
129  {
130  destMacAddress = m_gwAddress;
131  }
132 
133  Ptr<EncapKey> key;
135  {
136  key = Create<EncapKey>(m_nodeInfo->GetMacAddress(),
138  flowId,
139  m_nodeInfo->GetMacAddress(),
140  destMacAddress);
141  }
142  else
143  {
144  key = Create<EncapKey>(m_nodeInfo->GetMacAddress(),
145  destMacAddress,
146  flowId,
147  m_nodeInfo->GetMacAddress(),
148  destMacAddress);
149  }
150 
151  EncapContainer_t::iterator it = m_encaps.find(key);
152 
153  if (it == m_encaps.end())
154  {
160  CreateEncap(key);
161  it = m_encaps.find(key);
162  }
163 
164  // Add E2E address tag to identify the packet in lower layers
165  SatAddressE2ETag addressE2ETag;
166  addressE2ETag.SetE2EDestAddress(destMacAddress);
167  addressE2ETag.SetE2ESourceAddress(m_nodeInfo->GetMacAddress());
168  packet->AddPacketTag(addressE2ETag);
169 
170  it->second->EnquePdu(packet, destMacAddress);
171 
172  // Add packet trace entry:
173  m_packetTrace(Simulator::Now(),
175  m_nodeInfo->GetNodeType(),
176  m_nodeInfo->GetNodeId(),
177  m_nodeInfo->GetMacAddress(),
180  SatUtils::GetPacketInfo(packet));
181 
182  return true;
183 }
184 
185 Ptr<Packet>
187  Mac48Address utAddr,
188  uint8_t rcIndex,
189  uint32_t& bytesLeft,
190  uint32_t& nextMinTxO)
191 {
192  NS_LOG_FUNCTION(this << utAddr << bytes << (uint32_t)rcIndex);
193 
194  Ptr<Packet> packet;
195  Ptr<EncapKey> key;
197  {
198  key = Create<EncapKey>(utAddr, m_satelliteAddress, rcIndex);
199  }
200  else
201  {
202  key = Create<EncapKey>(utAddr, m_gwAddress, rcIndex);
203  }
204 
205  EncapContainer_t::iterator it = m_encaps.find(key);
206 
207  if (it != m_encaps.end())
208  {
209  packet = it->second->NotifyTxOpportunity(bytes, bytesLeft, nextMinTxO);
210 
211  if (packet)
212  {
214 
215  // Add packet trace entry:
216  m_packetTrace(Simulator::Now(),
218  m_nodeInfo->GetNodeType(),
219  m_nodeInfo->GetNodeId(),
220  m_nodeInfo->GetMacAddress(),
222  ld,
223  SatUtils::GetPacketInfo(packet));
224  }
225  }
226  /*
227  * At the UT the UT scheduler may give a Tx opportunity to a encapsulator which
228  * does not exist, since it does not exact knowledge that which encapsulators
229  * have been dynamically created. Thus, it is not an error case, where the
230  * encapsulator is not found!
231  */
232 
233  return packet;
234 }
235 
236 void
237 SatUtLlc::SetRequestManager(Ptr<SatRequestManager> rm)
238 {
239  NS_LOG_FUNCTION(this);
240  m_requestManager = rm;
241 }
242 
243 Ptr<SatRequestManager>
245 {
246  NS_LOG_FUNCTION(this);
247 
248  return m_requestManager;
249 }
250 
251 void
253 {
254  NS_LOG_FUNCTION(this);
255 
256  // Control queue = rcIndex 0
258  for (EncapContainer_t::iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
259  {
260  // Set the callback for each RLE queue
261  queueCb = MakeCallback(&SatQueue::GetQueueStatistics, it->second->GetQueue());
262  m_requestManager->AddQueueCallback(it->first->m_flowId, queueCb);
263  }
264 }
265 
266 uint32_t
267 SatUtLlc::GetNumSmallerPackets(uint32_t maxPacketSizeBytes) const
268 {
269  NS_LOG_FUNCTION(this << maxPacketSizeBytes);
270 
271  uint32_t packets(0);
272  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
273  {
274  packets += it->second->GetQueue()->GetNumSmallerPackets(maxPacketSizeBytes);
275  }
276  return packets;
277 }
278 
279 void
280 SatUtLlc::SetNodeInfo(Ptr<SatNodeInfo> nodeInfo)
281 {
282  NS_LOG_FUNCTION(this);
283 
284  m_requestManager->SetNodeInfo(nodeInfo);
285  SatLlc::SetNodeInfo(nodeInfo);
286 }
287 
288 void
289 SatUtLlc::CreateEncap(Ptr<EncapKey> key)
290 {
291  CreateEncap(key, NULL);
292 }
293 
294 void
295 SatUtLlc::CreateEncap(Ptr<EncapKey> key, Ptr<SatQueue> providedQueue)
296 {
297  NS_LOG_FUNCTION(this << key->m_encapAddress << key->m_decapAddress
298  << (uint32_t)(key->m_flowId));
299 
300  Ptr<SatBaseEncapsulator> utEncap;
301 
303  {
304  // Control packet
305  utEncap = CreateObject<SatBaseEncapsulator>(key->m_encapAddress,
306  key->m_decapAddress,
307  key->m_sourceE2EAddress,
308  key->m_destE2EAddress,
309  key->m_flowId);
310  }
311  else if (m_rtnLinkArqEnabled)
312  {
313  utEncap = CreateObject<SatReturnLinkEncapsulatorArq>(key->m_encapAddress,
314  key->m_decapAddress,
315  key->m_sourceE2EAddress,
316  key->m_destE2EAddress,
317  key->m_flowId,
319  }
320  else
321  {
322  utEncap = CreateObject<SatReturnLinkEncapsulator>(key->m_encapAddress,
323  key->m_decapAddress,
324  key->m_sourceE2EAddress,
325  key->m_destE2EAddress,
326  key->m_flowId,
328  }
329 
330  Ptr<SatQueue> queue = providedQueue;
331  if (!queue)
332  {
333  queue = CreateObject<SatQueue>(key->m_flowId);
334  queue->AddQueueEventCallback(m_macQueueEventCb);
335  queue->AddQueueEventCallback(
337 
338  // Set the callback for each RLE queue
340  MakeCallback(&SatQueue::GetQueueStatistics, queue);
341  m_requestManager->AddQueueCallback(key->m_flowId, queueCb);
342  }
343 
344  utEncap->SetQueue(queue);
345 
346  NS_LOG_INFO("Create encapsulator with key (" << key->m_encapAddress << ", "
347  << key->m_decapAddress << ", "
348  << (uint32_t)key->m_flowId << ")");
349 
350  // Store the encapsulator
351  std::pair<EncapContainer_t::iterator, bool> result =
352  m_encaps.insert(std::make_pair(key, utEncap));
353  if (result.second == false)
354  {
355  NS_FATAL_ERROR("Insert to map with key (" << key->m_encapAddress << ", "
356  << key->m_decapAddress << ", "
357  << (uint32_t)key->m_flowId << ") failed!");
358  }
359 }
360 
361 void
362 SatUtLlc::CreateDecap(Ptr<EncapKey> key)
363 {
364  NS_LOG_FUNCTION(this << key->m_encapAddress << key->m_decapAddress
365  << (uint32_t)(key->m_flowId));
366 
367  Ptr<SatBaseEncapsulator> utDecap;
368 
370  {
371  utDecap = CreateObject<SatGenericStreamEncapsulatorArq>(key->m_encapAddress,
372  key->m_decapAddress,
373  key->m_sourceE2EAddress,
374  key->m_destE2EAddress,
375  key->m_flowId,
377  }
378  else
379  {
380  utDecap = CreateObject<SatGenericStreamEncapsulator>(key->m_encapAddress,
381  key->m_decapAddress,
382  key->m_sourceE2EAddress,
383  key->m_destE2EAddress,
384  key->m_flowId,
386  }
387 
388  utDecap->SetReceiveCallback(MakeCallback(&SatLlc::ReceiveHigherLayerPdu, this));
389  utDecap->SetCtrlMsgCallback(m_sendCtrlCallback);
390 
391  NS_LOG_INFO("Create decapsulator with key (" << key->m_encapAddress << ", "
392  << key->m_decapAddress << ", "
393  << (uint32_t)key->m_flowId << ")");
394 
395  // Store the decapsulator
396  std::pair<EncapContainer_t::iterator, bool> result =
397  m_decaps.insert(std::make_pair(key, utDecap));
398  if (result.second == false)
399  {
400  NS_FATAL_ERROR("Insert to map with key (" << key->m_encapAddress << ", "
401  << key->m_decapAddress << ", "
402  << (uint32_t)key->m_flowId << ") failed!");
403  }
404 }
405 
406 uint32_t
407 SatUtLlc::GetNBytesInQueue(Mac48Address utAddress) const
408 {
409  NS_LOG_FUNCTION(this << utAddress);
410 
411  uint32_t sum = 0;
412 
413  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
414  {
415  if (it->first->m_encapAddress == utAddress)
416  {
417  NS_ASSERT(it->second != nullptr);
418  Ptr<SatQueue> queue = it->second->GetQueue();
419  NS_ASSERT(queue != nullptr);
420  sum += queue->GetNBytes();
421  }
422  }
423 
424  return sum;
425 }
426 
427 uint32_t
428 SatUtLlc::GetNPacketsInQueue(Mac48Address utAddress) const
429 {
430  NS_LOG_FUNCTION(this << utAddress);
431 
432  uint32_t sum = 0;
433 
434  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
435  {
436  if (it->first->m_encapAddress == utAddress)
437  {
438  NS_ASSERT(it->second != nullptr);
439  Ptr<SatQueue> queue = it->second->GetQueue();
440  NS_ASSERT(queue != nullptr);
441  sum += queue->GetNPackets();
442  }
443  }
444 
445  return sum;
446 }
447 
448 void
449 SatUtLlc::GetSchedulingContexts(std::vector<Ptr<SatSchedulingObject>>& output) const
450 {
451  NS_LOG_FUNCTION(this);
452  NS_ASSERT(false);
453 
457 }
458 
461 {
462  return SatEnums::LD_RETURN;
463 }
464 
467 {
468  return SatEnums::LD_FORWARD;
469 }
470 
471 void
473 {
474  NS_LOG_FUNCTION(this << &cb);
475 
476  m_macQueueEventCb = cb;
477 }
478 
479 void
480 SatUtLlc::SetGwAddress(Mac48Address address)
481 {
482  NS_LOG_FUNCTION(this << address);
483 
484  if (m_nodeInfo && m_nodeInfo->GetMacAddress() != address)
485  {
486  // Move queue from the old gateway to the new one
487  for (uint8_t rcIndex = 0;; ++rcIndex)
488  {
489  Ptr<EncapKey> peek =
490  Create<EncapKey>(m_nodeInfo->GetMacAddress(), m_gwAddress, rcIndex);
491  EncapContainer_t::iterator it = m_encaps.find(peek);
492 
493  if (it != m_encaps.end())
494  {
495  Ptr<EncapKey> key = Create<EncapKey>(m_nodeInfo->GetMacAddress(), address, rcIndex);
496  CreateEncap(key, it->second->GetQueue());
497  m_encaps.erase(it);
498  NS_LOG_INFO("Queue from key "
499  << peek->m_encapAddress << ", " << peek->m_decapAddress << ", "
500  << (uint32_t)(peek->m_flowId) << " moved to key " << key->m_encapAddress
501  << ", " << key->m_decapAddress << ", " << (uint32_t)(key->m_flowId));
502  }
503 
504  if (rcIndex == 255)
505  {
506  break;
507  }
508  }
509  }
510 
511  SatLlc::SetGwAddress(address);
512 
513  m_requestManager->SetGwAddress(address);
514 }
515 
516 } // namespace ns3
This class implements a tag that carries the satellite MAC of GW and UT.
void SetE2ESourceAddress(Mac48Address e2eSourceAddress)
Set E2E source MAC address.
void SetE2EDestAddress(Mac48Address e2eDestAddress)
Set E2E destination MAC address.
SatLinkDir_t
Link direction used for packet tracing.
RegenerationMode_t
The regeneration mode used in satellites.
Tag to store ground station destination address.
SatLlc base class holds the UT specific SatBaseEncapsulator instances, which are responsible of fragm...
Ptr< SatNodeInfo > m_nodeInfo
Node info containing node related information, such as node type, node id and MAC address (of the Sat...
virtual void SetGwAddress(Mac48Address address)
Set the GW address.
virtual uint32_t GetNBytesInQueue() const
Get the total number of (new) bytes in all encapsulators.
virtual void SetNodeInfo(Ptr< SatNodeInfo > nodeInfo)
Set the node info.
uint32_t m_additionalHeaderSize
Additional header size to add to encapsulation/decapsulation.
bool m_fwdLinkArqEnabled
Is FWD link ARQ enabled.
SatBaseEncapsulator::SendCtrlCallback m_sendCtrlCallback
Callback to send control messages.
SatEnums::RegenerationMode_t m_returnLinkRegenerationMode
Regeneration mode on return link.
EncapContainer_t m_decaps
Map of decapsulator base pointers.
TracedCallback< Time, SatEnums::SatPacketEvent_t, SatEnums::SatNodeType_t, uint32_t, Mac48Address, SatEnums::SatLogLevel_t, SatEnums::SatLinkDir_t, std::string > m_packetTrace
Trace callback used for packet tracing:
Mac48Address m_gwAddress
GW address.
virtual void DoDispose()
Dispose of this class instance.
EncapContainer_t m_encaps
Map of encapsulator base pointers.
virtual uint32_t GetNPacketsInQueue() const
Get the total number of (new) packets in all encapsulators.
virtual void ReceiveHigherLayerPdu(Ptr< Packet > packet, Mac48Address source, Mac48Address dest)
Receive HL PDU from encapsulator/decapsulator entity.
Mac48Address m_satelliteAddress
SAT address, used in case of network regeneration.
bool m_rtnLinkArqEnabled
Is RTN link ARQ enabled.
Callback< void, SatQueue::QueueEvent_t, uint8_t > QueueEventCallback
Callback to indicate queue related event.
QueueStats_t GetQueueStatistics(bool reset)
GetQueueStatistics returns a struct of KPIs.
void ReceiveQueueEvent(SatQueue::QueueEvent_t event, uint8_t rcIndex)
Receive a queue event.
Callback< SatQueue::QueueStats_t, bool > QueueCallback
Callback to fetch queue statistics.
void SetQueueStatisticsCallbacks()
Set queue statistics callbacks for each UT packet queue.
virtual SatEnums::SatLinkDir_t GetSatLinkRxDir()
Get the link RX direction.
void SetMacQueueEventCallback(SatQueue::QueueEventCallback cb)
SatQueue::QueueEventCallback m_macQueueEventCb
Callback to send queue events to e.g.
Ptr< SatRequestManager > m_requestManager
Request manager handling the capacity requests.
void SetRequestManager(Ptr< SatRequestManager > rm)
Set a request manager for UT's LLC instance.
virtual void CreateDecap(Ptr< EncapKey > key)
Virtual method to create a new decapsulator 'on-a-need-basis' dynamically.
virtual ~SatUtLlc()
Destroy a SatUtLlc.
virtual uint32_t GetNumSmallerPackets(uint32_t maxPacketSizeBytes) const
Method checks how many packets are smaller or equal in size than the maximum packets size threshold s...
SatUtLlc()
Construct a SatUtLlc, should not be used.
void SetGwAddress(Mac48Address address)
Set the GW address.
virtual void SetNodeInfo(Ptr< SatNodeInfo > nodeInfo)
Set the node info.
virtual void CreateEncap(Ptr< EncapKey > key)
Virtual method to create a new encapsulator 'on-a-need-basis' dynamically.
Ptr< SatRequestManager > GetRequestManager() const
Getter for the request manager.
void DoDispose()
Dispose of SatUtLLc.
static TypeId GetTypeId(void)
Derived form Object.
virtual bool Enque(Ptr< Packet > packet, Address dest, uint8_t flowId)
Called from higher layer (SatNetDevice) to enque packet to LLC.
virtual SatEnums::SatLinkDir_t GetSatLinkTxDir()
Get the link TX direction.
virtual Ptr< Packet > NotifyTxOpportunity(uint32_t bytes, Mac48Address utAddr, uint8_t rcIndex, uint32_t &bytesLeft, uint32_t &nextMinTxO)
Called from lower layer (MAC) to inform a Tx opportunity of certain amount of bytes.
virtual void GetSchedulingContexts(std::vector< Ptr< SatSchedulingObject >> &output) const
Create and fill the scheduling objects based on LLC layer information.
static std::string GetPacketInfo(const Ptr< const Packet > p)
Get packet information in std::string for printing purposes.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.