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-topology.h"
30 #include "satellite-typedefs.h"
31 #include "satellite-utils.h"
32 
33 #include <ns3/log.h>
34 #include <ns3/nstime.h>
35 #include <ns3/simulator.h>
36 #include <ns3/singleton.h>
37 
38 #include <utility>
39 
40 NS_LOG_COMPONENT_DEFINE("SatLlc");
41 
42 namespace ns3
43 {
44 
45 NS_OBJECT_ENSURE_REGISTERED(SatLlc);
46 
47 TypeId
49 {
50  static TypeId tid = TypeId("ns3::SatLlc")
51  .SetParent<Object>()
52  .AddAttribute("FwdLinkArqEnabled",
53  "Enable ARQ in forward link.",
54  BooleanValue(false),
55  MakeBooleanAccessor(&SatLlc::m_fwdLinkArqEnabled),
56  MakeBooleanChecker())
57  .AddAttribute("RtnLinkArqEnabled",
58  "Enable ARQ in return link.",
59  BooleanValue(false),
60  MakeBooleanAccessor(&SatLlc::m_rtnLinkArqEnabled),
61  MakeBooleanChecker())
62  .AddTraceSource("PacketTrace",
63  "Packet event trace",
64  MakeTraceSourceAccessor(&SatLlc::m_packetTrace),
65  "ns3::PacketTraceCallback");
66  return tid;
67 }
68 
70  : m_nodeInfo(),
71  m_encaps(),
72  m_decaps(),
73  m_fwdLinkArqEnabled(false),
74  m_rtnLinkArqEnabled(false),
75  m_gwAddress(),
76  m_satelliteAddress(),
77  m_additionalHeaderSize(0),
78  m_forwardLinkRegenerationMode(
79  Singleton<SatTopology>::Get()->GetForwardLinkRegenerationMode()),
80  m_returnLinkRegenerationMode(Singleton<SatTopology>::Get()->GetReturnLinkRegenerationMode())
81 {
82  NS_LOG_FUNCTION(this);
83 }
84 
86 {
87  NS_LOG_FUNCTION(this);
88 }
89 
90 void
92 {
93  NS_LOG_FUNCTION(this);
94  m_rxCallback.Nullify();
95 
96  EncapContainer_t::iterator it;
97 
98  for (it = m_encaps.begin(); it != m_encaps.end(); ++it)
99  {
100  it->second->DoDispose();
101  it->second = 0;
102  }
103  m_encaps.clear();
104 
105  for (it = m_decaps.begin(); it != m_decaps.end(); ++it)
106  {
107  it->second->DoDispose();
108  it->second = 0;
109  }
110  m_decaps.clear();
111 
112  Object::DoDispose();
113 }
114 
115 bool
116 SatLlc::Enque(Ptr<Packet> packet, Address dest, uint8_t flowId)
117 {
118  NS_LOG_FUNCTION(this << packet << dest << (uint32_t)flowId);
119  NS_LOG_INFO("p=" << packet);
120  NS_LOG_INFO("dest=" << dest);
121  NS_LOG_INFO("UID is " << packet->GetUid());
122 
123  Ptr<EncapKey> key = Create<EncapKey>(m_nodeInfo->GetMacAddress(),
124  Mac48Address::ConvertFrom(dest),
125  flowId,
126  m_nodeInfo->GetMacAddress(),
127  Mac48Address::ConvertFrom(dest));
128 
129  EncapContainer_t::iterator it = m_encaps.find(key);
130 
131  if (it == m_encaps.end())
132  {
138  CreateEncap(key);
139  it = m_encaps.find(key);
140  }
141 
142  // Store packet arrival time
143  SatTimeTag timeTag(Simulator::Now());
144  packet->AddPacketTag(timeTag);
145 
146  // Add E2E address tag to identify the packet in lower layers
147  SatAddressE2ETag addressE2ETag;
148  addressE2ETag.SetE2EDestAddress(Mac48Address::ConvertFrom(dest));
149  addressE2ETag.SetE2ESourceAddress(m_nodeInfo->GetMacAddress());
150  packet->AddPacketTag(addressE2ETag);
151 
152  it->second->EnquePdu(packet, Mac48Address::ConvertFrom(dest));
153 
155 
156  // Add packet trace entry:
157  m_packetTrace(Simulator::Now(),
159  m_nodeInfo->GetNodeType(),
160  m_nodeInfo->GetNodeId(),
161  m_nodeInfo->GetMacAddress(),
163  ld,
164  SatUtils::GetPacketInfo(packet));
165 
166  return true;
167 }
168 
169 void
170 SatLlc::Receive(Ptr<Packet> packet, Mac48Address source, Mac48Address dest)
171 {
172  NS_LOG_FUNCTION(this << source << dest << packet);
173 
175 
176  // Add packet trace entry:
177  m_packetTrace(Simulator::Now(),
179  m_nodeInfo->GetNodeType(),
180  m_nodeInfo->GetNodeId(),
181  m_nodeInfo->GetMacAddress(),
183  ld,
184  SatUtils::GetPacketInfo(packet));
185 
186  // Receive packet with a decapsulator instance which is handling the
187  // packets for this specific id
188  SatFlowIdTag flowIdTag;
189  bool mSuccess = packet->PeekPacketTag(flowIdTag);
190  if (mSuccess)
191  {
192  uint32_t flowId = flowIdTag.GetFlowId();
193  Ptr<EncapKey> key = Create<EncapKey>(source, dest, flowId);
194  EncapContainer_t::iterator it = m_decaps.find(key);
195 
196  // Control messages not received by this method
197  if (flowId == SatEnums::CONTROL_FID && m_nodeInfo->GetNodeType() != SatEnums::NT_SAT)
198  {
199  NS_FATAL_ERROR("Control messages should not be received by SatLlc::Receive () method!");
200  }
201 
202  if (it == m_decaps.end())
203  {
209  CreateDecap(key);
210  it = m_decaps.find(key);
211  }
212 
213  it->second->ReceivePdu(packet);
214  }
215 }
216 
217 void
218 SatLlc::ReceiveAck(Ptr<SatArqAckMessage> ack, Mac48Address source, Mac48Address dest)
219 {
220  NS_LOG_FUNCTION(this << source << dest);
221 
228  uint32_t flowId = ack->GetFlowId();
229 
230  Ptr<EncapKey> key = Create<EncapKey>(dest, source, flowId);
231  EncapContainer_t::iterator it = m_encaps.find(key);
232 
233  if (it != m_encaps.end())
234  {
235  it->second->ReceiveAck(ack);
236  }
237  else
238  {
239  NS_FATAL_ERROR("Encapsulator not found for key (" << source << ", " << dest << ", "
240  << (uint32_t)flowId << ")");
241  }
242 }
243 
246 {
247  return SatEnums::LD_UNDEFINED;
248 }
249 
252 {
253  return SatEnums::LD_UNDEFINED;
254 }
255 
256 void
257 SatLlc::ReceiveHigherLayerPdu(Ptr<Packet> packet, Mac48Address source, Mac48Address dest)
258 {
259  NS_LOG_FUNCTION(this << packet << source << dest);
260 
261  // Remove time tag
262  SatTimeTag timeTag;
263  packet->RemovePacketTag(timeTag);
264 
265  // Remove control msg tag
266  SatControlMsgTag ctrlTag;
267  bool cSuccess = packet->RemovePacketTag(ctrlTag);
268 
269  if (cSuccess)
270  {
271  if (ctrlTag.GetMsgType() != SatControlMsgTag::SAT_ARQ_ACK)
272  {
273  NS_FATAL_ERROR("A control message other than ARQ ACK received at the LLC!");
274  }
275 
276  // ARQ ACKs need to be forwarded to LLC/ARQ for processing
277  uint32_t ackId = ctrlTag.GetMsgId();
278 
279  Ptr<SatArqAckMessage> ack = DynamicCast<SatArqAckMessage>(m_readCtrlCallback(ackId));
280 
281  if (ack == nullptr)
282  {
283  NS_FATAL_ERROR(
284  "ARQ ACK not found, check that control msg storage time is set long enough!");
285  }
286 
287  ReceiveAck(ack, source, dest);
288  }
289  // Higher layer packet
290  else
291  {
292  // Call a callback to receive the packet at upper layer
293 
294  // Remove SatAddressE2ETag
295  SatAddressE2ETag addressE2ETag;
296  packet->RemovePacketTag(addressE2ETag);
297 
298  m_rxCallback(packet);
299  }
300 }
301 
302 void
303 SatLlc::AddEncap(Mac48Address source,
304  Mac48Address dest,
305  uint8_t flowId,
306  Ptr<SatBaseEncapsulator> enc)
307 {
308  NS_LOG_FUNCTION(this << source << dest << (uint32_t)flowId);
309 
310  Ptr<EncapKey> key = Create<EncapKey>(source, dest, flowId);
311  EncapContainer_t::iterator it = m_encaps.find(key);
312 
313  if (it == m_encaps.end())
314  {
315  NS_LOG_INFO("Add encapsulator with key (" << source << ", " << dest << ", "
316  << (uint32_t)flowId << ")");
317 
318  std::pair<EncapContainer_t::iterator, bool> result =
319  m_encaps.insert(std::make_pair(key, enc));
320  if (result.second == false)
321  {
322  NS_FATAL_ERROR("Insert to map with key (" << source << ", " << dest << ", "
323  << (uint32_t)flowId << ") failed!");
324  }
325  }
326  else
327  {
328  NS_FATAL_ERROR("Encapsulator container already holds key ("
329  << source << ", " << dest << ", " << (uint32_t)flowId << ") key!");
330  }
331 }
332 
333 void
334 SatLlc::AddDecap(Mac48Address source,
335  Mac48Address dest,
336  uint8_t flowId,
337  Ptr<SatBaseEncapsulator> dec)
338 {
339  NS_LOG_FUNCTION(this << source << dest << (uint32_t)flowId);
340 
341  Ptr<EncapKey> key = Create<EncapKey>(source, dest, flowId);
342  EncapContainer_t::iterator it = m_decaps.find(key);
343 
344  if (it == m_decaps.end())
345  {
346  NS_LOG_INFO("Add Decapsulator with key (" << source << ", " << dest << ", "
347  << (uint32_t)flowId << ")");
348 
349  std::pair<EncapContainer_t::iterator, bool> result =
350  m_decaps.insert(std::make_pair(key, dec));
351  if (result.second == false)
352  {
353  NS_FATAL_ERROR("Insert to map with key (" << source << ", " << dest << ", "
354  << (uint32_t)flowId << ") failed!");
355  }
356  }
357  else
358  {
359  NS_FATAL_ERROR("Decapsulator container already holds (" << source << ", " << dest << ", "
360  << (uint32_t)flowId << ") key!");
361  }
362 }
363 
364 void
365 SatLlc::SetNodeInfo(Ptr<SatNodeInfo> nodeInfo)
366 {
367  NS_LOG_FUNCTION(this << nodeInfo);
368  m_nodeInfo = nodeInfo;
369 }
370 
371 void
373 {
374  NS_LOG_FUNCTION(this << &cb);
375  m_rxCallback = cb;
376 }
377 
378 bool
380 {
381  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
382  {
383  if (it->second->GetTxBufferSizeInBytes() > 0)
384  {
385  return false;
386  }
387  }
388  return true;
389 }
390 
391 bool
393 {
394  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
395  {
396  if (it->first->m_flowId == SatEnums::CONTROL_FID)
397  {
398  if (it->second->GetTxBufferSizeInBytes() > 0)
399  {
400  return false;
401  }
402  }
403  }
404  return true;
405 }
406 
407 uint32_t
409 {
410  NS_LOG_FUNCTION(this);
411 
412  uint32_t sum = 0;
413 
414  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
415  {
416  NS_ASSERT(it->second != nullptr);
417  Ptr<SatQueue> queue = it->second->GetQueue();
418  NS_ASSERT(queue != nullptr);
419  sum += queue->GetNBytes();
420  }
421 
422  return sum;
423 }
424 
425 uint32_t
427 {
428  NS_LOG_FUNCTION(this);
429 
430  uint32_t sum = 0;
431 
432  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
433  {
434  NS_ASSERT(it->second != nullptr);
435  Ptr<SatQueue> queue = it->second->GetQueue();
436  NS_ASSERT(queue != nullptr);
437  sum += queue->GetNPackets();
438  }
439 
440  return sum;
441 }
442 
443 void
445 {
446  NS_LOG_FUNCTION(this << &cb);
447  m_readCtrlCallback = cb;
448 }
449 
450 void
452 {
453  NS_LOG_FUNCTION(this << &cb);
454 
455  m_sendCtrlCallback = cb;
456 }
457 
458 void
459 SatLlc::SetGwAddress(Mac48Address address)
460 {
461  NS_LOG_FUNCTION(this << address);
462  m_gwAddress = address;
463 }
464 
465 void
466 SatLlc::SetSatelliteAddress(Mac48Address address)
467 {
468  NS_LOG_FUNCTION(this << address);
469  m_satelliteAddress = address;
470 }
471 
472 void
473 SatLlc::SetAdditionalHeaderSize(uint32_t additionalHeaderSize)
474 {
475  NS_LOG_FUNCTION(this << additionalHeaderSize);
476  m_additionalHeaderSize = additionalHeaderSize;
477 }
478 
479 } // 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.
SatLinkDir_t
Link direction used for packet tracing.
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.
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.
Class to store topology of the whole system.
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.