satellite-return-link-encapsulator-arq.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 
22 
24 #include "satellite-arq-header.h"
26 #include "satellite-llc.h"
27 #include "satellite-mac-tag.h"
28 #include "satellite-queue.h"
29 #include "satellite-time-tag.h"
30 
31 #include <ns3/log.h>
32 #include <ns3/mac48-address.h>
33 #include <ns3/simulator.h>
34 
35 #include <algorithm>
36 
37 NS_LOG_COMPONENT_DEFINE("SatReturnLinkEncapsulatorArq");
38 
39 namespace ns3
40 {
41 
42 NS_OBJECT_ENSURE_REGISTERED(SatReturnLinkEncapsulatorArq);
43 
45  : m_seqNo(),
46  m_txedBuffer(),
47  m_retxBuffer(),
48  m_retxBufferSize(0),
49  m_txedBufferSize(0),
50  m_maxRtnArqSegmentSize(37),
51  m_maxNoOfRetransmissions(2),
52  m_retransmissionTimer(Seconds(0.6)),
53  m_arqWindowSize(10),
54  m_arqHeaderSize(1),
55  m_nextExpectedSeqNo(0)
56 {
57  NS_LOG_FUNCTION(this);
58  NS_ASSERT(false);
59 
63 }
64 
66  Mac48Address decapAddress,
67  Mac48Address sourceE2EAddress,
68  Mac48Address destE2EAddress,
69  uint8_t flowId,
70  uint32_t additionalHeaderSize)
71  : SatReturnLinkEncapsulator(encapAddress,
72  decapAddress,
73  sourceE2EAddress,
74  destE2EAddress,
75  flowId,
76  additionalHeaderSize),
77  m_seqNo(),
78  m_txedBuffer(),
79  m_retxBuffer(),
80  m_retxBufferSize(0),
81  m_txedBufferSize(0),
82  m_maxRtnArqSegmentSize(37),
83  m_maxNoOfRetransmissions(2),
84  m_retransmissionTimer(Seconds(0.6)),
85  m_arqWindowSize(10),
86  m_arqHeaderSize(1),
87  m_nextExpectedSeqNo(0)
88 {
89  NS_LOG_FUNCTION(this);
90 
91  ObjectBase::ConstructSelf(AttributeConstructionList());
92 
93  m_seqNo = Create<SatArqSequenceNumber>(m_arqWindowSize);
94 }
95 
97 {
98  NS_LOG_FUNCTION(this);
99 }
100 
101 TypeId
103 {
104  static TypeId tid =
105  TypeId("ns3::SatReturnLinkEncapsulatorArq")
106  .SetParent<SatReturnLinkEncapsulator>()
107  .AddConstructor<SatReturnLinkEncapsulatorArq>()
108  .AddAttribute(
109  "MaxRtnArqSegmentSize",
110  "Maximum return link ARQ segment size in Bytes.",
111  UintegerValue(37),
113  MakeUintegerChecker<uint32_t>())
114  .AddAttribute(
115  "MaxNoOfRetransmissions",
116  "Maximum number of retransmissions for a single RLE PDU.",
117  UintegerValue(2),
119  MakeUintegerChecker<uint32_t>())
120  .AddAttribute(
121  "RetransmissionTimer",
122  "Retransmission time value, i.e. how long to wait for ACK before retransmission.",
123  TimeValue(Seconds(0.6)),
125  MakeTimeChecker())
126  .AddAttribute(
127  "WindowSize",
128  "Window size for ARQ, i.e. how many simultaneous packets are allowed in the air.",
129  UintegerValue(10),
130  MakeUintegerAccessor(&SatReturnLinkEncapsulatorArq::m_arqWindowSize),
131  MakeUintegerChecker<uint32_t>())
132  .AddAttribute("ArqHeaderSize",
133  "ARQ header size in Bytes.",
134  UintegerValue(1),
135  MakeUintegerAccessor(&SatReturnLinkEncapsulatorArq::m_arqHeaderSize),
136  MakeUintegerChecker<uint32_t>())
137  .AddAttribute("RxWaitingTime",
138  "Time to wait for a packet at the reception (GW) before moving onwards "
139  "with the packet reception.",
140  TimeValue(Seconds(1.8)),
142  MakeTimeChecker());
143  return tid;
144 }
145 
146 TypeId
148 {
149  return GetTypeId();
150 }
151 
152 void
154 {
155  NS_LOG_FUNCTION(this);
156  m_seqNo = 0;
157 
158  // Clean-up the Tx'ed buffer
159  std::map<uint8_t, Ptr<SatArqBufferContext>>::iterator it = m_txedBuffer.begin();
160  while (it != m_txedBuffer.end())
161  {
162  it->second->DoDispose();
163  it->second = 0;
164  ++it;
165  }
166  m_txedBuffer.clear();
167 
168  // Clean-up the reTx buffer
169  it = m_retxBuffer.begin();
170  while (it != m_retxBuffer.end())
171  {
172  it->second->DoDispose();
173  it->second = 0;
174  ++it;
175  }
176  m_retxBuffer.clear();
177 
178  // Clean-up the reordering buffer
179  std::map<uint32_t, Ptr<SatArqBufferContext>>::iterator it2 = m_reorderingBuffer.begin();
180  while (it2 != m_reorderingBuffer.end())
181  {
182  it2->second->DoDispose();
183  it2->second = 0;
184  ++it2;
185  }
186  m_reorderingBuffer.clear();
187 
189 }
190 
191 Ptr<Packet>
193  uint32_t& bytesLeft,
194  uint32_t& nextMinTxO)
195 {
196  NS_LOG_FUNCTION(this << bytes);
197  NS_LOG_INFO("TxOpportunity for UT: " << m_encapAddress << " flowId: " << (uint32_t)m_flowId
198  << " of " << bytes << " bytes");
199 
200  // Payload adapted PDU = NULL
201  Ptr<Packet> packet;
202 
208  if (!m_retxBuffer.empty())
209  {
210  // Oldest seqNo sent first
211  Ptr<SatArqBufferContext> context = m_retxBuffer.begin()->second;
212 
213  // If the packet fits into the transmission opportunity
214  if (context->m_pdu->GetSize() <= bytes)
215  {
216  // Pop the front
217  m_retxBuffer.erase(m_retxBuffer.begin());
218 
219  // Increase the retransmission counter
220  context->m_retransmissionCount = context->m_retransmissionCount + 1;
221 
222  m_retxBufferSize -= context->m_pdu->GetSize();
223  m_txedBufferSize += context->m_pdu->GetSize();
224 
225  // Store it back to the transmitted packet container.
226  m_txedBuffer.insert(std::make_pair(context->m_seqNo, context));
227 
228  // Create the retransmission event and store it to the context. Event is cancelled if a
229  // ACK is received. However, if the event triggers, we shall send the packet again, if
230  // the packet still has retransmissions left.
231  EventId t = Simulator::Schedule(m_retransmissionTimer,
233  this,
234  context->m_seqNo);
235  context->m_waitingTimer = t;
236 
237  NS_LOG_INFO("UT: << " << m_encapAddress << " sent a retransmission packet of size: "
238  << context->m_pdu->GetSize()
239  << " with seqNo: " << (uint32_t)(context->m_seqNo)
240  << " flowId: " << (uint32_t)(m_flowId));
241 
242  Ptr<Packet> copy = context->m_pdu->Copy();
243  return copy;
244  }
245  else
246  {
247  NS_LOG_INFO("Retransmission PDU: " << context->m_pdu->GetUid()
248  << " size: " << context->m_pdu->GetSize()
249  << " does not fit into TxO: " << bytes);
250  }
251  }
252 
253  // Check the transmission buffer. Sequence number needs to be
254  // available for any new transmissions.
255  else if (!m_txQueue->IsEmpty() && m_seqNo->SeqNoAvailable())
256  {
257  // Crate new RLE PDU
259 
260  if (packet)
261  {
262  // Add MAC tag to identify the packet in lower layers
263  SatMacTag mTag;
264  if (!packet->PeekPacketTag(mTag))
265  {
268  packet->AddPacketTag(mTag);
269  }
270 
271  // Add E2E address tag to identify the packet in lower layers
272  SatAddressE2ETag addressE2ETag;
273  if (!packet->PeekPacketTag(addressE2ETag))
274  {
275  addressE2ETag.SetE2EDestAddress(m_destE2EAddress);
277  packet->AddPacketTag(addressE2ETag);
278  }
279 
280  // Add flow id tag
281  SatFlowIdTag flowIdTag;
282  flowIdTag.SetFlowId(m_flowId);
283  packet->AddPacketTag(flowIdTag);
284 
285  // Get next available sequence number
286  uint8_t seqNo = m_seqNo->NextSequenceNumber();
287 
288  // Add ARQ header
289  SatArqHeader arqHeader;
290  arqHeader.SetSeqNo(seqNo);
291  packet->AddHeader(arqHeader);
292 
293  // Create ARQ context and store it to Tx'ed buffer
294  Ptr<SatArqBufferContext> arqContext = CreateObject<SatArqBufferContext>();
295  arqContext->m_retransmissionCount = 0;
296  Ptr<Packet> copy = packet->Copy();
297  arqContext->m_pdu = copy;
298  arqContext->m_seqNo = seqNo;
299 
300  // Create the retransmission event and store it to the context. Event is cancelled if a
301  // ACK is received. However, if the event triggers, we shall send the packet again, if
302  // the packet still has retransmissions left.
303  arqContext->m_waitingTimer =
304  Simulator::Schedule(m_retransmissionTimer,
306  this,
307  seqNo);
308 
309  // Update the buffer status
310  m_txedBufferSize += packet->GetSize();
311  m_txedBuffer.insert(std::make_pair(seqNo, arqContext));
312 
313  if (packet->GetSize() > bytes)
314  {
315  NS_FATAL_ERROR("Created packet of size: " << packet->GetSize()
316  << " is larger than the tx opportunity: "
317  << bytes);
318  }
319 
320  NS_LOG_INFO("UT: << " << m_encapAddress << " sent a packet of size: "
321  << packet->GetSize() << " with seqNo: " << (uint32_t)(seqNo)
322  << " flowId: " << (uint32_t)(m_flowId));
323  NS_LOG_INFO("Queue size after TxOpportunity: " << m_txQueue->GetNBytes());
324  }
325  }
326  else if (!m_seqNo->SeqNoAvailable())
327  {
328  bytesLeft = 0;
329  return packet;
330  }
331 
332  // Update bytes lefts
333  bytesLeft = GetTxBufferSizeInBytes();
334 
335  // Update min TxO
336  nextMinTxO = GetMinTxOpportunityInBytes();
337 
338  return packet;
339 }
340 
341 void
343 {
344  NS_LOG_FUNCTION(this << (uint32_t)seqNo);
345 
346  NS_LOG_INFO("At UT: " << m_encapAddress
347  << " ARQ retransmission timer expired for: " << (uint32_t)(seqNo));
348 
349  std::map<uint8_t, Ptr<SatArqBufferContext>>::iterator it = m_txedBuffer.find(seqNo);
350 
351  if (it != m_txedBuffer.end())
352  {
353  NS_ASSERT(seqNo == it->second->m_seqNo);
354  NS_ASSERT(it->second->m_pdu);
355 
356  // Retransmission still possible
357  if (it->second->m_retransmissionCount < m_maxNoOfRetransmissions)
358  {
359  NS_LOG_INFO("Moving the ARQ context to retransmission buffer");
360 
361  Ptr<SatArqBufferContext> context = it->second;
362 
363  m_txedBuffer.erase(it);
364  m_retxBufferSize += context->m_pdu->GetSize();
365 
366  // Push to the retransmission buffer
367  m_retxBuffer.insert(std::make_pair(seqNo, context));
368  }
369  // Maximum retransmissions reached
370  else
371  {
372  NS_LOG_INFO("For UT: " << m_encapAddress << " max retransmissions reached for "
373  << (uint32_t)(seqNo));
374 
375  // Do clean-up
376  CleanUp(seqNo);
377  }
378  }
379  else
380  {
381  NS_LOG_INFO("Element not found anymore in the m_txedBuffer, thus ACK has been received "
382  "already earlier");
383  }
384 }
385 
386 void
388 {
389  NS_LOG_FUNCTION(this << (uint32_t)sequenceNumber);
390 
391  // Release sequence number
392  m_seqNo->Release(sequenceNumber);
393 
394  // Clean-up the Tx'ed buffer
395  std::map<uint8_t, Ptr<SatArqBufferContext>>::iterator it = m_txedBuffer.find(sequenceNumber);
396  if (it != m_txedBuffer.end())
397  {
398  NS_LOG_INFO("Sequence no: " << (uint32_t)sequenceNumber << " clean up from txedBuffer!");
399  m_txedBufferSize -= it->second->m_pdu->GetSize();
400  it->second->DoDispose();
401  it->second = 0;
402  m_txedBuffer.erase(it);
403  }
404 
405  // Clean-up the reTx buffer
406  it = m_retxBuffer.find(sequenceNumber);
407  if (it != m_retxBuffer.end())
408  {
409  NS_LOG_INFO("Sequence no: " << (uint32_t)sequenceNumber << " clean up from retxBuffer!");
410  m_retxBufferSize -= it->second->m_pdu->GetSize();
411  it->second->DoDispose();
412  it->second = 0;
413  m_retxBuffer.erase(it);
414  }
415 }
416 
417 void
419 {
420  NS_LOG_FUNCTION(this);
421 
427  NS_LOG_INFO("UT: " << m_encapAddress
428  << " received ACK with SN: " << (uint32_t)(ack->GetSequenceNumber()));
429 
430  // Do clean-up
431  CleanUp(ack->GetSequenceNumber());
432 }
433 
434 void
436 {
437  NS_LOG_FUNCTION(this << p->GetSize());
438 
439  // Remove encap PDU status tag
440  SatEncapPduStatusTag statusTag;
441  p->RemovePacketTag(statusTag);
442 
443  // Remove flow id tag
444  SatFlowIdTag flowIdTag;
445  p->RemovePacketTag(flowIdTag);
446 
447  // Sanity check
448  SatMacTag mTag;
449  bool mSuccess = p->RemovePacketTag(mTag);
450  if (!mSuccess)
451  {
452  NS_FATAL_ERROR("MAC tag not found in the packet!");
453  }
454  else if (mTag.GetDestAddress() != m_decapAddress)
455  {
456  NS_FATAL_ERROR("Packet was not intended for this receiver!");
457  }
458 
459  SatArqHeader arqHeader;
460  p->RemoveHeader(arqHeader);
461  uint8_t seqNo = arqHeader.GetSeqNo();
462 
463  NS_LOG_INFO("UT: " << m_encapAddress << " received a packet with SeqNo: " << (uint32_t)(seqNo));
464 
465  // Send ACK for the received RLE packet.
466  SendAck(seqNo);
467 
468  // Convert the 8-bit sequence number to continuous 32-bit sequence number
469  uint32_t sn = ConvertSeqNo(seqNo);
470 
471  NS_LOG_INFO("8bit SN: " << (uint32_t)(seqNo) << " 32bit SN: " << sn);
472 
473  // If the received SN is valid. If we receive a SN from the past
474  // nothing is needed to be done.
475  if (sn >= m_nextExpectedSeqNo)
476  {
477  std::map<uint32_t, Ptr<SatArqBufferContext>>::iterator it = m_reorderingBuffer.find(sn);
478 
479  // If the context is not found, then we create a new one.
480  if (it == m_reorderingBuffer.end())
481  {
482  NS_LOG_INFO("UT: " << m_encapAddress
483  << " created a new ARQ buffer entry for SeqNo: " << sn);
484  Ptr<SatArqBufferContext> arqContext = CreateObject<SatArqBufferContext>();
485  arqContext->m_pdu = p;
486  arqContext->m_rxStatus = true;
487  arqContext->m_seqNo = sn;
488  arqContext->m_retransmissionCount = 0;
489  m_reorderingBuffer.insert(std::make_pair(sn, arqContext));
490  }
491  // If the context is found, update it.
492  else
493  {
494  NS_LOG_INFO("UT: " << m_encapAddress
495  << " reset an existing ARQ entry for SeqNo: " << sn);
496  it->second->m_waitingTimer.Cancel();
497  it->second->m_pdu = p;
498  it->second->m_rxStatus = true;
499  }
500 
501  NS_LOG_INFO("Received a packet with SeqNo: " << sn
502  << ", expecting: " << m_nextExpectedSeqNo);
503 
504  // If this is not the SN we expect
505  if (sn != m_nextExpectedSeqNo)
506  {
507  // Add context
508  for (uint32_t i = m_nextExpectedSeqNo; i < sn; ++i)
509  {
510  std::map<uint32_t, Ptr<SatArqBufferContext>>::iterator it2 =
511  m_reorderingBuffer.find(i);
512 
513  NS_LOG_INFO("Finding context for " << i);
514 
515  // If context not found
516  if (it2 == m_reorderingBuffer.end())
517  {
518  NS_LOG_INFO("Context NOT found for SeqNo: " << i);
519 
520  Ptr<SatArqBufferContext> arqContext = CreateObject<SatArqBufferContext>();
521  arqContext->m_pdu = NULL;
522  arqContext->m_rxStatus = false;
523  arqContext->m_seqNo = i;
524  arqContext->m_retransmissionCount = 0;
525  m_reorderingBuffer.insert(std::make_pair(i, arqContext));
526  EventId id =
527  Simulator::Schedule(m_rxWaitingTimer,
529  this,
530  i);
531  arqContext->m_waitingTimer = id;
532  }
533  }
534  }
535  // An expected sequence number received, reassemble and receive.
536  else
537  {
539  }
540  }
541  else
542  {
543  NS_LOG_INFO("UT: " << m_encapAddress << " received a packet with SeqNo: " << sn
544  << " which is already received!");
545  }
546 }
547 
548 uint32_t
550 {
551  NS_LOG_FUNCTION(this << (uint32_t)seqNo);
552 
553  uint32_t globalSeqNo(0);
554 
555  // Calculate the rounds and current seq no from m_nextExpectedSeqNo
556  uint32_t rounds = (m_nextExpectedSeqNo / std::numeric_limits<uint8_t>::max());
557  uint32_t rawSeqNo = m_nextExpectedSeqNo % std::numeric_limits<uint8_t>::max();
558 
559  NS_LOG_INFO("Input: " << (uint32_t)(seqNo) << " rounds: " << rounds << " rawSeqNo: " << rawSeqNo
560  << " windowSize: " << m_arqWindowSize
561  << " next expected: " << m_nextExpectedSeqNo);
562 
563  // Received sequence number is higher than the expected one.
564  if (seqNo >= rawSeqNo)
565  {
566  // If seqNo is from previous round
567  if ((seqNo - rawSeqNo) > 2 * m_arqWindowSize)
568  {
569  rounds--;
570  }
571  }
572  // seqNo < rawSeqNo
573  else
574  {
575  if ((rawSeqNo - seqNo) > 2 * m_arqWindowSize)
576  {
577  rounds++;
578  }
579  }
580 
581  globalSeqNo = rounds * std::numeric_limits<uint8_t>::max() + seqNo;
582 
583  return globalSeqNo;
584 }
585 
586 void
588 {
589  NS_LOG_FUNCTION(this);
590 
591  // Start from the expected sequence number iterator
592  std::map<uint32_t, Ptr<SatArqBufferContext>>::iterator it = m_reorderingBuffer.begin();
593 
594  NS_LOG_INFO("Process SeqNo: " << it->first << ", expected: " << m_nextExpectedSeqNo
595  << ", status: " << it->second->m_rxStatus);
596 
601  while (it != m_reorderingBuffer.end() && it->first == m_nextExpectedSeqNo &&
602  it->second->m_rxStatus == true)
603  {
604  NS_LOG_INFO("Process SeqNo: " << it->first << ", expected: " << m_nextExpectedSeqNo
605  << ", status: " << it->second->m_rxStatus);
606 
607  // If timer is running, cancel it.
608  if (it->second->m_waitingTimer.IsRunning())
609  {
610  it->second->m_waitingTimer.Cancel();
611  }
612 
613  // If PDU == NULL, it means that the RxWaitingTimer has expired
614  // without PDU being received
615  if (it->second->m_pdu)
616  {
617  // Process the PDU
618  ProcessPdu(it->second->m_pdu);
619  }
620 
621  m_reorderingBuffer.erase(it);
622  it = m_reorderingBuffer.begin();
623 
624  // Increase the seq no
626 
627  NS_LOG_INFO("Increasing SeqNo to " << m_nextExpectedSeqNo);
628  }
629 }
630 
631 void
633 {
634  NS_LOG_FUNCTION(this << seqNo);
635 
636  NS_LOG_INFO("For UT: " << m_encapAddress << " max waiting time reached for SeqNo: " << seqNo);
637  NS_LOG_INFO("Mark the PDU received and move forward!");
638 
639  // Find waiting timer, erase it and mark the packet received.
640  std::map<uint32_t, Ptr<SatArqBufferContext>>::iterator it = m_reorderingBuffer.find(seqNo);
641  if (it != m_reorderingBuffer.end())
642  {
643  it->second->m_waitingTimer.Cancel();
644  it->second->m_rxStatus = true;
645  }
646  else
647  {
648  NS_FATAL_ERROR("Rx waiting timer is not running anymore even though it expired!");
649  }
650 
652 }
653 
654 uint32_t
656 {
657  NS_LOG_FUNCTION(this);
658 
659  return m_txQueue->GetNBytes() + m_retxBufferSize;
660 }
661 
662 void
664 {
665  NS_LOG_FUNCTION(this << (uint32_t)seqNo);
666 
667  NS_LOG_INFO("GW: " << m_decapAddress << " send ACK to UT: " << m_encapAddress
668  << " with flowId: " << (uint32_t)(m_flowId)
669  << " with SN: " << (uint32_t)(seqNo));
670 
677  if (!m_ctrlCallback.IsNull())
678  {
679  Ptr<SatArqAckMessage> ack = Create<SatArqAckMessage>();
680  ack->SetSequenceNumber(seqNo);
681  ack->SetFlowId(m_flowId);
682 
683  // Source address (UT) is used here, since the in RTN the GW is
684  // sending the ACK to the UT.
686  }
687  else
688  {
689  NS_FATAL_ERROR("Unable to send ACK, since the Ctrl callback is NULL!");
690  }
691 }
692 
693 } // 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.
ARQ header implementation contains the sequence number related to the packet in question.
uint8_t GetSeqNo() const
Get sequence number.
void SetSeqNo(uint8_t seqNo)
Set sequence number.
Mac48Address m_encapAddress
Source and destination mac addresses.
Ptr< SatQueue > m_txQueue
Used queue in satellite encapsulator.
SendCtrlCallback m_ctrlCallback
Callback to send control messages.
SatEncapPduStatusTag is used temporarily to tag packets with the fragmentation status in the encapsul...
SatFlowIdTag implements a tag which carries the flow identifier of a packet.
void SetFlowId(uint8_t flowId)
Set flow id.
This class implements a tag that carries the satellite MAC specific information, such as source and d...
void SetDestAddress(Mac48Address dest)
Set destination MAC address.
Mac48Address GetDestAddress(void) const
Get destination MAC address.
void SetSourceAddress(Mac48Address source)
Set source MAC address.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.