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 #include <utility>
43 #include <vector>
44 
45 NS_LOG_COMPONENT_DEFINE("SatUtLlc");
46 
47 namespace ns3
48 {
49 
50 NS_OBJECT_ENSURE_REGISTERED(SatLlc);
51 
52 TypeId
54 {
55  static TypeId tid = TypeId("ns3::SatUtLlc")
56  .SetParent<SatLlc>()
57  .AddConstructor<SatUtLlc>()
58  .AddAttribute("SatRequestManager",
59  "The request manager of this UT.",
60  PointerValue(),
61  MakePointerAccessor(&SatUtLlc::GetRequestManager,
63  MakePointerChecker<SatRequestManager>());
64  return tid;
65 }
66 
68  : SatLlc(),
69  m_requestManager()
70 {
71  NS_LOG_FUNCTION(this);
72 }
73 
75 {
76  NS_LOG_FUNCTION(this);
77 }
78 
79 void
81 {
82  NS_LOG_FUNCTION(this);
83 
84  if (m_requestManager)
85  {
86  m_requestManager->DoDispose();
87  m_requestManager = 0;
88  }
89 
90  m_macQueueEventCb.Nullify();
91 
93 }
94 
95 bool
96 SatUtLlc::Enque(Ptr<Packet> packet, Address dest, uint8_t flowId)
97 {
98  NS_LOG_FUNCTION(this << packet << dest << (uint32_t)flowId);
99  NS_LOG_INFO("p=" << packet);
100  NS_LOG_INFO("dest=" << dest);
101  NS_LOG_INFO("UID is " << packet->GetUid());
102 
103  Mac48Address destMacAddress;
104  if (dest != m_satelliteAddress)
105  {
106  destMacAddress = Mac48Address::ConvertFrom(m_gwAddress);
107  }
108  else
109  {
110  destMacAddress = Mac48Address::ConvertFrom(dest);
111  }
112 
114  {
115  SatGroundStationAddressTag groundStationAddressTag =
116  SatGroundStationAddressTag(destMacAddress);
117  packet->AddPacketTag(groundStationAddressTag);
118  }
119 
120  // all multicast traffic is delivered with GW address
121  // in order to avoid supporting several encaps in UT
122  // in return link there is only one receiver (GW) for the multicast traffic for the UT
123  if (destMacAddress.IsGroup())
124  {
125  destMacAddress = m_gwAddress;
126  }
127 
128  Ptr<EncapKey> key;
130  {
131  key = Create<EncapKey>(m_nodeInfo->GetMacAddress(),
133  flowId,
134  m_nodeInfo->GetMacAddress(),
135  destMacAddress);
136  }
137  else
138  {
139  key = Create<EncapKey>(m_nodeInfo->GetMacAddress(),
140  destMacAddress,
141  flowId,
142  m_nodeInfo->GetMacAddress(),
143  destMacAddress);
144  }
145 
146  EncapContainer_t::iterator it = m_encaps.find(key);
147 
148  if (it == m_encaps.end())
149  {
155  CreateEncap(key);
156  it = m_encaps.find(key);
157  }
158 
159  // Add E2E address tag to identify the packet in lower layers
160  SatAddressE2ETag addressE2ETag;
161  addressE2ETag.SetE2EDestAddress(destMacAddress);
162  addressE2ETag.SetE2ESourceAddress(m_nodeInfo->GetMacAddress());
163  packet->AddPacketTag(addressE2ETag);
164 
165  it->second->EnquePdu(packet, destMacAddress);
166 
167  // Add packet trace entry:
168  m_packetTrace(Simulator::Now(),
170  m_nodeInfo->GetNodeType(),
171  m_nodeInfo->GetNodeId(),
172  m_nodeInfo->GetMacAddress(),
175  SatUtils::GetPacketInfo(packet));
176 
177  return true;
178 }
179 
180 Ptr<Packet>
182  Mac48Address utAddr,
183  uint8_t rcIndex,
184  uint32_t& bytesLeft,
185  uint32_t& nextMinTxO)
186 {
187  NS_LOG_FUNCTION(this << utAddr << bytes << (uint32_t)rcIndex);
188 
189  Ptr<Packet> packet;
190  Ptr<EncapKey> key;
192  {
193  key = Create<EncapKey>(utAddr, m_satelliteAddress, rcIndex);
194  }
195  else
196  {
197  key = Create<EncapKey>(utAddr, m_gwAddress, rcIndex);
198  }
199 
200  EncapContainer_t::iterator it = m_encaps.find(key);
201 
202  if (it != m_encaps.end())
203  {
204  packet = it->second->NotifyTxOpportunity(bytes, bytesLeft, nextMinTxO);
205 
206  if (packet)
207  {
209 
210  // Add packet trace entry:
211  m_packetTrace(Simulator::Now(),
213  m_nodeInfo->GetNodeType(),
214  m_nodeInfo->GetNodeId(),
215  m_nodeInfo->GetMacAddress(),
217  ld,
218  SatUtils::GetPacketInfo(packet));
219  }
220  }
221  /*
222  * At the UT the UT scheduler may give a Tx opportunity to a encapsulator which
223  * does not exist, since it does not exact knowledge that which encapsulators
224  * have been dynamically created. Thus, it is not an error case, where the
225  * encapsulator is not found!
226  */
227 
228  return packet;
229 }
230 
231 void
232 SatUtLlc::SetRequestManager(Ptr<SatRequestManager> rm)
233 {
234  NS_LOG_FUNCTION(this);
235  m_requestManager = rm;
236 }
237 
238 Ptr<SatRequestManager>
240 {
241  NS_LOG_FUNCTION(this);
242 
243  return m_requestManager;
244 }
245 
246 void
248 {
249  NS_LOG_FUNCTION(this);
250 
251  // Control queue = rcIndex 0
253  for (EncapContainer_t::iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
254  {
255  // Set the callback for each RLE queue
256  queueCb = MakeCallback(&SatQueue::GetQueueStatistics, it->second->GetQueue());
257  m_requestManager->AddQueueCallback(it->first->m_flowId, queueCb);
258  }
259 }
260 
261 uint32_t
262 SatUtLlc::GetNumSmallerPackets(uint32_t maxPacketSizeBytes) const
263 {
264  NS_LOG_FUNCTION(this << maxPacketSizeBytes);
265 
266  uint32_t packets(0);
267  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
268  {
269  packets += it->second->GetQueue()->GetNumSmallerPackets(maxPacketSizeBytes);
270  }
271  return packets;
272 }
273 
274 void
275 SatUtLlc::SetNodeInfo(Ptr<SatNodeInfo> nodeInfo)
276 {
277  NS_LOG_FUNCTION(this);
278 
279  m_requestManager->SetNodeInfo(nodeInfo);
280  SatLlc::SetNodeInfo(nodeInfo);
281 }
282 
283 void
284 SatUtLlc::CreateEncap(Ptr<EncapKey> key)
285 {
286  CreateEncap(key, nullptr);
287 }
288 
289 void
290 SatUtLlc::CreateEncap(Ptr<EncapKey> key, Ptr<SatQueue> providedQueue)
291 {
292  NS_LOG_FUNCTION(this << key->m_encapAddress << key->m_decapAddress
293  << (uint32_t)(key->m_flowId));
294 
295  Ptr<SatBaseEncapsulator> utEncap;
296 
298  {
299  // Control packet
300  utEncap = CreateObject<SatBaseEncapsulator>(key->m_encapAddress,
301  key->m_decapAddress,
302  key->m_sourceE2EAddress,
303  key->m_destE2EAddress,
304  key->m_flowId);
305  }
306  else if (m_rtnLinkArqEnabled)
307  {
308  utEncap = CreateObject<SatReturnLinkEncapsulatorArq>(key->m_encapAddress,
309  key->m_decapAddress,
310  key->m_sourceE2EAddress,
311  key->m_destE2EAddress,
312  key->m_flowId,
314  }
315  else
316  {
317  utEncap = CreateObject<SatReturnLinkEncapsulator>(key->m_encapAddress,
318  key->m_decapAddress,
319  key->m_sourceE2EAddress,
320  key->m_destE2EAddress,
321  key->m_flowId,
323  }
324 
325  Ptr<SatQueue> queue = providedQueue;
326  if (!queue)
327  {
328  queue = CreateObject<SatQueue>(key->m_flowId);
329  queue->AddQueueEventCallback(m_macQueueEventCb);
330  queue->AddQueueEventCallback(
332 
333  // Set the callback for each RLE queue
335  MakeCallback(&SatQueue::GetQueueStatistics, queue);
336  m_requestManager->AddQueueCallback(key->m_flowId, queueCb);
337  }
338 
339  utEncap->SetQueue(queue);
340 
341  NS_LOG_INFO("Create encapsulator with key (" << key->m_encapAddress << ", "
342  << key->m_decapAddress << ", "
343  << (uint32_t)key->m_flowId << ")");
344 
345  // Store the encapsulator
346  std::pair<EncapContainer_t::iterator, bool> result =
347  m_encaps.insert(std::make_pair(key, utEncap));
348  if (result.second == false)
349  {
350  NS_FATAL_ERROR("Insert to map with key (" << key->m_encapAddress << ", "
351  << key->m_decapAddress << ", "
352  << (uint32_t)key->m_flowId << ") failed!");
353  }
354 }
355 
356 void
357 SatUtLlc::CreateDecap(Ptr<EncapKey> key)
358 {
359  NS_LOG_FUNCTION(this << key->m_encapAddress << key->m_decapAddress
360  << (uint32_t)(key->m_flowId));
361 
362  Ptr<SatBaseEncapsulator> utDecap;
363 
365  {
366  utDecap = CreateObject<SatGenericStreamEncapsulatorArq>(key->m_encapAddress,
367  key->m_decapAddress,
368  key->m_sourceE2EAddress,
369  key->m_destE2EAddress,
370  key->m_flowId,
372  }
373  else
374  {
375  utDecap = CreateObject<SatGenericStreamEncapsulator>(key->m_encapAddress,
376  key->m_decapAddress,
377  key->m_sourceE2EAddress,
378  key->m_destE2EAddress,
379  key->m_flowId,
381  }
382 
383  utDecap->SetReceiveCallback(MakeCallback(&SatLlc::ReceiveHigherLayerPdu, this));
384  utDecap->SetCtrlMsgCallback(m_sendCtrlCallback);
385 
386  NS_LOG_INFO("Create decapsulator with key (" << key->m_encapAddress << ", "
387  << key->m_decapAddress << ", "
388  << (uint32_t)key->m_flowId << ")");
389 
390  // Store the decapsulator
391  std::pair<EncapContainer_t::iterator, bool> result =
392  m_decaps.insert(std::make_pair(key, utDecap));
393  if (result.second == false)
394  {
395  NS_FATAL_ERROR("Insert to map with key (" << key->m_encapAddress << ", "
396  << key->m_decapAddress << ", "
397  << (uint32_t)key->m_flowId << ") failed!");
398  }
399 }
400 
401 uint32_t
402 SatUtLlc::GetNBytesInQueue(Mac48Address utAddress) const
403 {
404  NS_LOG_FUNCTION(this << utAddress);
405 
406  uint32_t sum = 0;
407 
408  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
409  {
410  if (it->first->m_encapAddress == utAddress)
411  {
412  NS_ASSERT(it->second != nullptr);
413  Ptr<SatQueue> queue = it->second->GetQueue();
414  NS_ASSERT(queue != nullptr);
415  sum += queue->GetNBytes();
416  }
417  }
418 
419  return sum;
420 }
421 
422 uint32_t
423 SatUtLlc::GetNPacketsInQueue(Mac48Address utAddress) const
424 {
425  NS_LOG_FUNCTION(this << utAddress);
426 
427  uint32_t sum = 0;
428 
429  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
430  {
431  if (it->first->m_encapAddress == utAddress)
432  {
433  NS_ASSERT(it->second != nullptr);
434  Ptr<SatQueue> queue = it->second->GetQueue();
435  NS_ASSERT(queue != nullptr);
436  sum += queue->GetNPackets();
437  }
438  }
439 
440  return sum;
441 }
442 
443 void
444 SatUtLlc::GetSchedulingContexts(std::vector<Ptr<SatSchedulingObject>>& output) const
445 {
446  NS_LOG_FUNCTION(this);
447  NS_ASSERT(false);
448 
452 }
453 
456 {
457  return SatEnums::LD_RETURN;
458 }
459 
462 {
463  return SatEnums::LD_FORWARD;
464 }
465 
466 void
468 {
469  NS_LOG_FUNCTION(this << &cb);
470 
471  m_macQueueEventCb = cb;
472 }
473 
474 void
475 SatUtLlc::SetGwAddress(Mac48Address address)
476 {
477  NS_LOG_FUNCTION(this << address);
478 
479  if (m_nodeInfo && m_nodeInfo->GetMacAddress() != address)
480  {
481  // Move queue from the old gateway to the new one
482  for (uint8_t rcIndex = 0;; ++rcIndex)
483  {
484  Ptr<EncapKey> peek =
485  Create<EncapKey>(m_nodeInfo->GetMacAddress(), m_gwAddress, rcIndex);
486  EncapContainer_t::iterator it = m_encaps.find(peek);
487 
488  if (it != m_encaps.end())
489  {
490  Ptr<EncapKey> key = Create<EncapKey>(m_nodeInfo->GetMacAddress(), address, rcIndex);
491  CreateEncap(key, it->second->GetQueue());
492  m_encaps.erase(it);
493  NS_LOG_INFO("Queue from key "
494  << peek->m_encapAddress << ", " << peek->m_decapAddress << ", "
495  << (uint32_t)(peek->m_flowId) << " moved to key " << key->m_encapAddress
496  << ", " << key->m_decapAddress << ", " << (uint32_t)(key->m_flowId));
497  }
498 
499  if (rcIndex == 255)
500  {
501  break;
502  }
503  }
504  }
505 
506  SatLlc::SetGwAddress(address);
507 
508  m_requestManager->SetGwAddress(address);
509 }
510 
511 } // 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.
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.
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.