satellite-orbiter-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: Bastien TAURAN <bastien.tauran@viveris.fr>
19  */
20 
21 #include "satellite-orbiter-llc.h"
22 
24 #include "satellite-time-tag.h"
25 #include "satellite-utils.h"
26 
27 #include <utility>
28 #include <vector>
29 
30 NS_LOG_COMPONENT_DEFINE("SatOrbiterLlc");
31 
32 namespace ns3
33 {
34 
35 NS_OBJECT_ENSURE_REGISTERED(SatOrbiterLlc);
36 
37 TypeId
39 {
40  static TypeId tid = TypeId("ns3::SatOrbiterLlc").SetParent<SatLlc>();
41  return tid;
42 }
43 
45  : SatLlc()
46 {
47  NS_LOG_FUNCTION(this);
48 }
49 
51 {
52  NS_LOG_FUNCTION(this);
53 }
54 
55 void
57 {
58  Object::DoDispose();
59 }
60 
61 void
63 {
65 }
66 
67 bool
68 SatOrbiterLlc::Enque(Ptr<Packet> packet, Address dest, uint8_t flowId)
69 {
70  NS_LOG_FUNCTION(this << packet << dest << (uint32_t)flowId);
71  NS_LOG_INFO("p=" << packet);
72  NS_LOG_INFO("dest=" << dest);
73  NS_LOG_INFO("UID is " << packet->GetUid());
74 
75  Ptr<EncapKey> key = Create<EncapKey>(m_nodeInfo->GetMacAddress(),
76  Mac48Address::ConvertFrom(dest),
77  flowId,
78  m_nodeInfo->GetMacAddress(),
79  Mac48Address::ConvertFrom(dest));
80 
81  EncapContainer_t::iterator it = m_encaps.find(key);
82 
83  if (it == m_encaps.end())
84  {
90  CreateEncap(key);
91  it = m_encaps.find(key);
92  }
93 
94  it->second->EnquePdu(packet, Mac48Address::ConvertFrom(dest));
95 
97 
98  // Add packet trace entry:
99  m_packetTrace(Simulator::Now(),
101  m_nodeInfo->GetNodeType(),
102  m_nodeInfo->GetNodeId(),
103  m_nodeInfo->GetMacAddress(),
105  ld,
106  SatUtils::GetPacketInfo(packet));
107 
108  return true;
109 }
110 
111 Ptr<Packet>
113  Mac48Address utAddr,
114  uint8_t flowId,
115  uint32_t& bytesLeft,
116  uint32_t& nextMinTxO)
117 {
118  NS_LOG_FUNCTION(this << utAddr << bytes << (uint32_t)flowId);
119 
120  Ptr<Packet> packet;
121  Ptr<EncapKey> key = Create<EncapKey>(m_nodeInfo->GetMacAddress(), utAddr, flowId);
122  EncapContainer_t::iterator it = m_encaps.find(key);
123 
124  if (it != m_encaps.end())
125  {
126  packet = it->second->NotifyTxOpportunity(bytes, bytesLeft, nextMinTxO);
127 
128  if (packet)
129  {
131 
132  // Add packet trace entry:
133  m_packetTrace(Simulator::Now(),
135  m_nodeInfo->GetNodeType(),
136  m_nodeInfo->GetNodeId(),
137  m_nodeInfo->GetMacAddress(),
139  ld,
140  SatUtils::GetPacketInfo(packet));
141  }
142  }
143  else
144  {
145  NS_FATAL_ERROR("Encapsulator not found for key (" << m_nodeInfo->GetMacAddress() << ", "
146  << utAddr << ", " << (uint32_t)flowId
147  << ")");
148  }
149 
150  return packet;
151 }
152 
153 void
154 SatOrbiterLlc::ReceiveHigherLayerPdu(Ptr<Packet> packet, Mac48Address source, Mac48Address dest)
155 {
156  NS_LOG_FUNCTION(this << packet << source << dest);
157 
158  // Peek control msg tag
159  SatControlMsgTag ctrlTag;
160  bool cSuccess = packet->PeekPacketTag(ctrlTag);
161 
162  if (cSuccess)
163  {
164  if (ctrlTag.GetMsgType() != SatControlMsgTag::SAT_ARQ_ACK)
165  {
166  m_rxSatelliteCallback(packet, m_nodeInfo->GetMacAddress());
167  return;
168  }
169 
170  // ARQ ACKs need to be forwarded to LLC/ARQ for processing
171  uint32_t ackId = ctrlTag.GetMsgId();
172 
173  Ptr<SatArqAckMessage> ack = DynamicCast<SatArqAckMessage>(m_readCtrlCallback(ackId));
174 
175  if (ack == nullptr)
176  {
177  NS_FATAL_ERROR(
178  "ARQ ACK not found, check that control msg storage time is set long enough!");
179  }
180 
181  ReceiveAck(ack, source, dest);
182  }
183  // Higher layer packet
184  else
185  {
186  m_rxSatelliteCallback(packet, m_nodeInfo->GetMacAddress());
187  }
188 }
189 
190 void
191 SatOrbiterLlc::CreateEncap(Ptr<EncapKey> key)
192 {
193  NS_LOG_FUNCTION(this << key->m_encapAddress << key->m_decapAddress
194  << (uint32_t)(key->m_flowId));
195 
196  Ptr<SatBaseEncapsulator> encap = CreateObject<SatBaseEncapsulator>(key->m_encapAddress,
197  key->m_decapAddress,
198  key->m_sourceE2EAddress,
199  key->m_destE2EAddress,
200  key->m_flowId);
201 
202  Ptr<SatQueue> queue = CreateObject<SatQueue>(key->m_flowId);
203  encap->SetQueue(queue);
204 
205  NS_LOG_INFO("Create encapsulator with key (" << key->m_encapAddress << ", "
206  << key->m_decapAddress << ", "
207  << (uint32_t)key->m_flowId << ")");
208 
209  // Store the encapsulator
210  std::pair<EncapContainer_t::iterator, bool> result =
211  m_encaps.insert(std::make_pair(key, encap));
212  if (result.second == false)
213  {
214  NS_FATAL_ERROR("Insert to map with key (" << key->m_encapAddress << ", "
215  << key->m_decapAddress << ", "
216  << (uint32_t)key->m_flowId << ") failed!");
217  }
218 }
219 
220 void
221 SatOrbiterLlc::CreateDecap(Ptr<EncapKey> key)
222 {
223  NS_LOG_FUNCTION(this << key->m_encapAddress << key->m_decapAddress
224  << (uint32_t)(key->m_flowId));
225 
226  Ptr<SatBaseEncapsulator> decap = CreateObject<SatBaseEncapsulator>(key->m_encapAddress,
227  key->m_decapAddress,
228  key->m_sourceE2EAddress,
229  key->m_destE2EAddress,
230  key->m_flowId);
231 
232  decap->SetReceiveCallback(MakeCallback(&SatLlc::ReceiveHigherLayerPdu, this));
233  decap->SetCtrlMsgCallback(m_sendCtrlCallback);
234 
235  NS_LOG_INFO("Create decapsulator with key (" << key->m_encapAddress << ", "
236  << key->m_decapAddress << ", "
237  << (uint32_t)key->m_flowId << ")");
238 
239  // Store the decapsulator
240  std::pair<EncapContainer_t::iterator, bool> result =
241  m_decaps.insert(std::make_pair(key, decap));
242  if (result.second == false)
243  {
244  NS_FATAL_ERROR("Insert to map with key (" << key->m_encapAddress << ", "
245  << key->m_decapAddress << ", "
246  << (uint32_t)key->m_flowId << ") failed!");
247  }
248 }
249 
250 void
251 SatOrbiterLlc::GetSchedulingContexts(std::vector<Ptr<SatSchedulingObject>>& output) const
252 {
253  NS_LOG_FUNCTION(this);
254 
255  // Head of link queuing delay
256  Time holDelay;
257 
258  // Then the user data
259  for (EncapContainer_t::const_iterator cit = m_encaps.begin(); cit != m_encaps.end(); ++cit)
260  {
261  uint32_t buf = cit->second->GetTxBufferSizeInBytes();
262 
263  if (buf > 0)
264  {
265  holDelay = cit->second->GetHolDelay();
266  uint32_t minTxOpportunityInBytes = cit->second->GetMinTxOpportunityInBytes();
267  Ptr<SatSchedulingObject> so = Create<SatSchedulingObject>(cit->first->m_decapAddress,
268  buf,
269  minTxOpportunityInBytes,
270  holDelay,
271  cit->first->m_flowId);
272  output.push_back(so);
273  }
274  }
275 }
276 
277 uint32_t
278 SatOrbiterLlc::GetNBytesInQueue(Mac48Address utAddress) const
279 {
280  NS_LOG_FUNCTION(this << utAddress);
281 
282  uint32_t sum = 0;
283 
284  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
285  {
286  if (it->first->m_encapAddress == utAddress)
287  {
288  NS_ASSERT(it->second != nullptr);
289  Ptr<SatQueue> queue = it->second->GetQueue();
290  NS_ASSERT(queue != nullptr);
291  sum += queue->GetNBytes();
292  }
293  }
294 
295  return sum;
296 }
297 
298 uint32_t
299 SatOrbiterLlc::GetNPacketsInQueue(Mac48Address utAddress) const
300 {
301  NS_LOG_FUNCTION(this << utAddress);
302 
303  uint32_t sum = 0;
304 
305  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
306  {
307  if (it->first->m_encapAddress == utAddress)
308  {
309  NS_ASSERT(it->second != nullptr);
310  Ptr<SatQueue> queue = it->second->GetQueue();
311  NS_ASSERT(queue != nullptr);
312  sum += queue->GetNPackets();
313  }
314  }
315 
316  return sum;
317 }
318 
319 void
321 {
322  NS_LOG_FUNCTION(this);
323 
324  for (EncapContainer_t::const_iterator it = m_encaps.begin(); it != m_encaps.end(); ++it)
325  {
326  NS_ASSERT(it->second != nullptr);
327  Ptr<SatQueue> queue = it->second->GetQueue();
328  NS_ASSERT(queue != nullptr);
329  queue->DequeueAll();
330  }
331 }
332 
333 } // namespace ns3
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.
SatLlc base class holds the UT specific SatBaseEncapsulator instances, which are responsible of fragm...
virtual SatEnums::SatLinkDir_t GetSatLinkTxDir()
Get the link TX direction.
Ptr< SatNodeInfo > m_nodeInfo
Node info containing node related information, such as node type, node id and MAC address (of the Sat...
SatLlc::ReadCtrlMsgCallback m_readCtrlCallback
The read control message callback.
virtual uint32_t GetNBytesInQueue() const
Get the total number of (new) bytes in all encapsulators.
SatBaseEncapsulator::SendCtrlCallback m_sendCtrlCallback
Callback to send control messages.
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:
virtual void ReceiveAck(Ptr< SatArqAckMessage > ack, Mac48Address source, Mac48Address dest)
Receive a control msg (ARQ ACK) from lower layer.
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.
virtual void CreateEncap(Ptr< EncapKey > key)
Virtual method to create a new encapsulator 'on-a-need-basis' dynamically.
virtual ~SatOrbiterLlc()
Destroy a SatOrbiterLlc.
virtual void DoDispose()
Dispose of this class instance.
Callback< void, Ptr< Packet >, const Address & > ReceiveSatelliteCallback
Receive callback used for sending packet to netdevice layer.
virtual void ReceiveHigherLayerPdu(Ptr< Packet > packet, Mac48Address source, Mac48Address dest)
Receive HL PDU from encapsulator/decapsulator entity.
virtual bool Enque(Ptr< Packet > packet, Address dest, uint8_t flowId)
Called from higher layer (SatNetDevice) to enque packet to LLC.
static TypeId GetTypeId(void)
Derived from Object.
virtual void CreateDecap(Ptr< EncapKey > key)
Virtual method to create a new decapsulator 'on-a-need-basis' dynamically.
SatOrbiterLlc()
Construct a SatOrbiterLlc.
virtual void ClearQueues()
Remove all packets from the queues.
virtual Ptr< Packet > NotifyTxOpportunity(uint32_t bytes, Mac48Address utAddr, uint8_t flowId, 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.
ReceiveSatelliteCallback m_rxSatelliteCallback
The upper layer package receive callback.
void SetReceiveSatelliteCallback(SatOrbiterLlc::ReceiveSatelliteCallback cb)
Set Receive callback to forward packet to upper layer on satellite.
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.