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