satellite-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-llc.h"
22 
24 #include "satellite-enums.h"
25 #include "satellite-node-info.h"
26 #include "satellite-queue.h"
28 #include "satellite-time-tag.h"
29 #include "satellite-typedefs.h"
30 #include "satellite-utils.h"
31 
32 #include <ns3/log.h>
33 #include <ns3/nstime.h>
34 #include <ns3/simulator.h>
35 
36 NS_LOG_COMPONENT_DEFINE("SatLlc");
37 
38 namespace ns3
39 {
40 
41 NS_OBJECT_ENSURE_REGISTERED(SatLlc);
42 
43 TypeId
45 {
46  static TypeId tid = TypeId("ns3::SatLlc")
47  .SetParent<Object>()
48  .AddAttribute("FwdLinkArqEnabled",
49  "Enable ARQ in forward link.",
50  BooleanValue(false),
51  MakeBooleanAccessor(&SatLlc::m_fwdLinkArqEnabled),
52  MakeBooleanChecker())
53  .AddAttribute("RtnLinkArqEnabled",
54  "Enable ARQ in return link.",
55  BooleanValue(false),
56  MakeBooleanAccessor(&SatLlc::m_rtnLinkArqEnabled),
57  MakeBooleanChecker())
58  .AddTraceSource("PacketTrace",
59  "Packet event trace",
60  MakeTraceSourceAccessor(&SatLlc::m_packetTrace),
61  "ns3::PacketTraceCallback");
62  return tid;
63 }
64 
66  : m_nodeInfo(),
67  m_encaps(),
68  m_decaps(),
69  m_fwdLinkArqEnabled(false),
70  m_rtnLinkArqEnabled(false),
71  m_gwAddress(),
72  m_satelliteAddress(),
73  m_additionalHeaderSize(0),
74  m_forwardLinkRegenerationMode(SatEnums::TRANSPARENT),
75  m_returnLinkRegenerationMode(SatEnums::TRANSPARENT)
76 {
77  NS_LOG_FUNCTION(this);
78  NS_ASSERT(false); // this version of the constructor should not been used
79 }
80 
81 SatLlc::SatLlc(SatEnums::RegenerationMode_t forwardLinkRegenerationMode,
82  SatEnums::RegenerationMode_t returnLinkRegenerationMode)
83  : m_nodeInfo(),
84  m_encaps(),
85  m_decaps(),
86  m_fwdLinkArqEnabled(false),
87  m_rtnLinkArqEnabled(false),
88  m_gwAddress(),
89  m_satelliteAddress(),
90  m_additionalHeaderSize(0),
91  m_forwardLinkRegenerationMode(forwardLinkRegenerationMode),
92  m_returnLinkRegenerationMode(returnLinkRegenerationMode)
93 {
94  NS_LOG_FUNCTION(this);
95 }
96 
98 {
99  NS_LOG_FUNCTION(this);
100 }
101 
102 void
104 {
105  NS_LOG_FUNCTION(this);
106  m_rxCallback.Nullify();
107 
108  EncapContainer_t::iterator it;
109 
110  for (it = m_encaps.begin(); it != m_encaps.end(); ++it)
111  {
112  it->second->DoDispose();
113  it->second = 0;
114  }
115  m_encaps.clear();
116 
117  for (it = m_decaps.begin(); it != m_decaps.end(); ++it)
118  {
119  it->second->DoDispose();
120  it->second = 0;
121  }
122  m_decaps.clear();
123 
124  Object::DoDispose();
125 }
126 
127 bool
128 SatLlc::Enque(Ptr<Packet> packet, Address dest, uint8_t flowId)
129 {
130  NS_LOG_FUNCTION(this << packet << dest << (uint32_t)flowId);
131  NS_LOG_INFO("p=" << packet);
132  NS_LOG_INFO("dest=" << dest);
133  NS_LOG_INFO("UID is " << packet->GetUid());
134 
135  Ptr<EncapKey> key = Create<EncapKey>(m_nodeInfo->GetMacAddress(),
136  Mac48Address::ConvertFrom(dest),
137  flowId,
138  m_nodeInfo->GetMacAddress(),
139  Mac48Address::ConvertFrom(dest));
140 
141  EncapContainer_t::iterator it = m_encaps.find(key);
142 
143  if (it == m_encaps.end())
144  {
150  CreateEncap(key);
151  it = m_encaps.find(key);
152  }
153 
154  // Store packet arrival time
155  SatTimeTag timeTag(Simulator::Now());
156  packet->AddPacketTag(timeTag);
157 
158  // Add E2E address tag to identify the packet in lower layers
159  SatAddressE2ETag addressE2ETag;
160  addressE2ETag.SetE2EDestAddress(Mac48Address::ConvertFrom(dest));
161  addressE2ETag.SetE2ESourceAddress(m_nodeInfo->GetMacAddress());
162  packet->AddPacketTag(addressE2ETag);
163 
164  it->second->EnquePdu(packet, Mac48Address::ConvertFrom(dest));
165 
167 
168  // Add packet trace entry:
169  m_packetTrace(Simulator::Now(),
171  m_nodeInfo->GetNodeType(),
172  m_nodeInfo->GetNodeId(),
173  m_nodeInfo->GetMacAddress(),
175  ld,
176  SatUtils::GetPacketInfo(packet));
177 
178  return true;
179 }
180 
181 void
182 SatLlc::Receive(Ptr<Packet> packet, Mac48Address source, Mac48Address dest)
183 {
184  NS_LOG_FUNCTION(this << source << dest << packet);
185 
187 
188  // Add packet trace entry:
189  m_packetTrace(Simulator::Now(),
191  m_nodeInfo->GetNodeType(),
192  m_nodeInfo->GetNodeId(),
193  m_nodeInfo->GetMacAddress(),
195  ld,
196  SatUtils::GetPacketInfo(packet));
197 
198  // Receive packet with a decapsulator instance which is handling the
199  // packets for this specific id
200  SatFlowIdTag flowIdTag;
201  bool mSuccess = packet->PeekPacketTag(flowIdTag);
202  if (mSuccess)
203  {
204  uint32_t flowId = flowIdTag.GetFlowId();
205  Ptr<EncapKey> key = Create<EncapKey>(source, dest, flowId);
206  EncapContainer_t::iterator it = m_decaps.find(key);
207 
208  // Control messages not received by this method
209  if (flowId == SatEnums::CONTROL_FID && m_nodeInfo->GetNodeType() != SatEnums::NT_SAT)
210  {
211  NS_FATAL_ERROR("Control messages should not be received by SatLlc::Receive () method!");
212  }
213 
214  if (it == m_decaps.end())
215  {
221  CreateDecap(key);
222  it = m_decaps.find(key);
223  }
224 
225  it->second->ReceivePdu(packet);
226  }
227 }
228 
229 void
230 SatLlc::ReceiveAck(Ptr<SatArqAckMessage> ack, Mac48Address source, Mac48Address dest)
231 {
232  NS_LOG_FUNCTION(this << source << dest);
233 
240  uint32_t flowId = ack->GetFlowId();
241 
242  Ptr<EncapKey> key = Create<EncapKey>(dest, source, flowId);
243  EncapContainer_t::iterator it = m_encaps.find(key);
244 
245  if (it != m_encaps.end())
246  {
247  it->second->ReceiveAck(ack);
248  }
249  else
250  {
251  NS_FATAL_ERROR("Encapsulator not found for key (" << source << ", " << dest << ", "
252  << (uint32_t)flowId << ")");
253  }
254 }
255 
258 {
259  return SatEnums::LD_UNDEFINED;
260 }
261 
264 {
265  return SatEnums::LD_UNDEFINED;
266 }
267 
268 void
269 SatLlc::ReceiveHigherLayerPdu(Ptr<Packet> packet, Mac48Address source, Mac48Address dest)
270 {
271  NS_LOG_FUNCTION(this << packet << source << dest);
272 
273  // Remove time tag
274  SatTimeTag timeTag;
275  packet->RemovePacketTag(timeTag);
276 
277  // Remove control msg tag
278  SatControlMsgTag ctrlTag;
279  bool cSuccess = packet->RemovePacketTag(ctrlTag);
280 
281  if (cSuccess)
282  {
283  if (ctrlTag.GetMsgType() != SatControlMsgTag::SAT_ARQ_ACK)
284  {
285  NS_FATAL_ERROR("A control message other than ARQ ACK received at the LLC!");
286  }
287 
288  // ARQ ACKs need to be forwarded to LLC/ARQ for processing
289  uint32_t ackId = ctrlTag.GetMsgId();
290 
291  Ptr<SatArqAckMessage> ack = DynamicCast<SatArqAckMessage>(m_readCtrlCallback(ackId));
292 
293  if (ack == NULL)
294  {
295  NS_FATAL_ERROR(
296  "ARQ ACK not found, check that control msg storage time is set long enough!");
297  }
298 
299  ReceiveAck(ack, source, dest);
300  }
301  // Higher layer packet
302  else
303  {
304  // Call a callback to receive the packet at upper layer
305 
306  // Remove SatAddressE2ETag
307  SatAddressE2ETag addressE2ETag;
308  packet->RemovePacketTag(addressE2ETag);
309 
310  m_rxCallback(packet);
311  }
312 }
313 
314 void
315 SatLlc::AddEncap(Mac48Address source,
316  Mac48Address dest,
317  uint8_t flowId,
318  Ptr<SatBaseEncapsulator> enc)
319 {
320  NS_LOG_FUNCTION(this << source << dest << (uint32_t)flowId);
321 
322  Ptr<EncapKey> key = Create<EncapKey>(source, dest, flowId);
323  EncapContainer_t::iterator it = m_encaps.find(key);
324 
325  if (it == m_encaps.end())
326  {
327  NS_LOG_INFO("Add encapsulator with key (" << source << ", " << dest << ", "
328  << (uint32_t)flowId << ")");
329 
330  std::pair<EncapContainer_t::iterator, bool> result =
331  m_encaps.insert(std::make_pair(key, enc));
332  if (result.second == false)
333  {
334  NS_FATAL_ERROR("Insert to map with key (" << source << ", " << dest << ", "
335  << (uint32_t)flowId << ") failed!");
336  }
337  }
338  else
339  {
340  NS_FATAL_ERROR("Encapsulator container already holds key ("
341  << source << ", " << dest << ", " << (uint32_t)flowId << ") key!");
342  }
343 }
344 
345 void
346 SatLlc::AddDecap(Mac48Address source,
347  Mac48Address dest,
348  uint8_t flowId,
349  Ptr<SatBaseEncapsulator> dec)
350 {
351  NS_LOG_FUNCTION(this << source << dest << (uint32_t)flowId);
352 
353  Ptr<EncapKey> key = Create<EncapKey>(source, dest, flowId);
354  EncapContainer_t::iterator it = m_decaps.find(key);
355 
356  if (it == m_decaps.end())
357  {
358  NS_LOG_INFO("Add Decapsulator with key (" << source << ", " << dest << ", "
359  << (uint32_t)flowId << ")");
360 
361  std::pair<EncapContainer_t::iterator, bool> result =
362  m_decaps.insert(std::make_pair(key, dec));
363  if (result.second == false)
364  {
365  NS_FATAL_ERROR("Insert to map with key (" << source << ", " << dest << ", "
366  << (uint32_t)flowId << ") failed!");
367  }
368  }
369  else
370  {
371  NS_FATAL_ERROR("Decapsulator container already holds (" << source << ", " << dest << ", "
372  << (uint32_t)flowId << ") key!");
373  }
374 }
375 
376 void
377 SatLlc::SetNodeInfo(Ptr<SatNodeInfo> nodeInfo)
378 {
379  NS_LOG_FUNCTION(this << nodeInfo);
380  m_nodeInfo = nodeInfo;
381 }
382 
383 void
385 {
386  NS_LOG_FUNCTION(this << &cb);
387  m_rxCallback = cb;
388 }
389 
390 bool
392 {
393  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
394  {
395  if (it->second->GetTxBufferSizeInBytes() > 0)
396  {
397  return false;
398  }
399  }
400  return true;
401 }
402 
403 bool
405 {
406  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
407  {
408  if (it->first->m_flowId == SatEnums::CONTROL_FID)
409  {
410  if (it->second->GetTxBufferSizeInBytes() > 0)
411  {
412  return false;
413  }
414  }
415  }
416  return true;
417 }
418 
419 uint32_t
421 {
422  NS_LOG_FUNCTION(this);
423 
424  uint32_t sum = 0;
425 
426  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
427  {
428  NS_ASSERT(it->second != nullptr);
429  Ptr<SatQueue> queue = it->second->GetQueue();
430  NS_ASSERT(queue != nullptr);
431  sum += queue->GetNBytes();
432  }
433 
434  return sum;
435 }
436 
437 uint32_t
439 {
440  NS_LOG_FUNCTION(this);
441 
442  uint32_t sum = 0;
443 
444  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
445  {
446  NS_ASSERT(it->second != nullptr);
447  Ptr<SatQueue> queue = it->second->GetQueue();
448  NS_ASSERT(queue != nullptr);
449  sum += queue->GetNPackets();
450  }
451 
452  return sum;
453 }
454 
455 void
457 {
458  NS_LOG_FUNCTION(this << &cb);
459  m_readCtrlCallback = cb;
460 }
461 
462 void
464 {
465  NS_LOG_FUNCTION(this << &cb);
466 
467  m_sendCtrlCallback = cb;
468 }
469 
470 void
471 SatLlc::SetGwAddress(Mac48Address address)
472 {
473  NS_LOG_FUNCTION(this << address);
474  m_gwAddress = address;
475 }
476 
477 void
478 SatLlc::SetSatelliteAddress(Mac48Address address)
479 {
480  NS_LOG_FUNCTION(this << address);
481  m_satelliteAddress = address;
482 }
483 
484 void
485 SatLlc::SetAdditionalHeaderSize(uint32_t additionalHeaderSize)
486 {
487  NS_LOG_FUNCTION(this << additionalHeaderSize);
488  m_additionalHeaderSize = additionalHeaderSize;
489 }
490 
491 } // 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.
Callback< bool, Ptr< SatControlMessage >, const Address & > SendCtrlCallback
Control msg sending callback.
This class implements a tag that is used to identify control messages (packages).
virtual uint32_t GetMsgId() const
Get message type specific identifier.
SatControlMsgType_t GetMsgType(void) const
Get type of the control message.
SatEnums class is for simplifying the use of enumerators in the satellite module.
SatLinkDir_t
Link direction used for packet tracing.
RegenerationMode_t
The regeneration mode used in satellites.
SatFlowIdTag implements a tag which carries the flow identifier of a packet.
uint8_t GetFlowId() const
Get flow identifier.
virtual SatEnums::SatLinkDir_t GetSatLinkTxDir()
Get the link TX direction.
virtual bool BuffersEmpty() const
Are buffers empty?
static TypeId GetTypeId(void)
Derived from Object.
virtual SatEnums::SatLinkDir_t GetSatLinkRxDir()
Get the link RX direction.
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.
SatLlc::ReadCtrlMsgCallback m_readCtrlCallback
The read control message callback.
Callback< Ptr< SatControlMessage >, uint32_t > ReadCtrlMsgCallback
Callback to read control messages from container storing control messages.
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.
void SetReadCtrlCallback(SatLlc::ReadCtrlMsgCallback cb)
Method to set read control message callback.
uint32_t m_additionalHeaderSize
Additional header size to add to encapsulation/decapsulation.
void SetReceiveCallback(SatLlc::ReceiveCallback cb)
Set Receive callback to forward packet to upper layer.
bool m_fwdLinkArqEnabled
Is FWD link ARQ enabled.
SatBaseEncapsulator::SendCtrlCallback m_sendCtrlCallback
Callback to send control messages.
EncapContainer_t m_decaps
Map of decapsulator base pointers.
virtual void CreateEncap(Ptr< EncapKey > key)=0
Virtual method to create a new encapsulator 'on-a-need-basis' dynamically.
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:
virtual void CreateDecap(Ptr< EncapKey > key)=0
Virtual method to create a new decapsulator 'on-a-need-basis' dynamically.
Mac48Address m_gwAddress
GW address.
virtual void DoDispose()
Dispose of this class instance.
void AddEncap(Mac48Address source, Mac48Address dest, uint8_t flowId, Ptr< SatBaseEncapsulator > enc)
Add an encapsulator entry for the LLC.
virtual void ReceiveAck(Ptr< SatArqAckMessage > ack, Mac48Address source, Mac48Address dest)
Receive a control msg (ARQ ACK) from lower layer.
void SetCtrlMsgCallback(SatBaseEncapsulator::SendCtrlCallback cb)
EncapContainer_t m_encaps
Map of encapsulator base pointers.
virtual ~SatLlc()
Destroy a SatLlc.
void SetAdditionalHeaderSize(uint32_t additionalHeaderSize)
Set the additional header size.
virtual bool ControlBuffersEmpty() const
Are buffers empty?
SatLlc()
Construct a SatLlc, should not be used.
virtual void SetSatelliteAddress(Mac48Address address)
Set the SAT address.
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.
Callback< void, Ptr< const Packet > > ReceiveCallback
Receive callback used for sending packet to netdevice layer.
virtual bool Enque(Ptr< Packet > packet, Address dest, uint8_t flowId)
Called from higher layer (SatNetDevice) to enque packet to LLC.
Mac48Address m_satelliteAddress
SAT address, used in case of network regeneration.
void AddDecap(Mac48Address source, Mac48Address dest, uint8_t flowId, Ptr< SatBaseEncapsulator > dec)
Add an decapsulator entry for the LLC.
bool m_rtnLinkArqEnabled
Is RTN link ARQ enabled.
virtual void Receive(Ptr< Packet > packet, Mac48Address source, Mac48Address dest)
Receive user data packet from lower layer.
ReceiveCallback m_rxCallback
The upper layer package receive callback.
Time tag used to identify the time when packet is enqueued at LLC level.
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.