RlcSduSlidingWindowTransmissionBuffer.h Source File

Simu5G: RlcSduSlidingWindowTransmissionBuffer.h Source File
Simu5G
RlcSduSlidingWindowTransmissionBuffer.h
1//
2// Simu5G
3//
4// Authors: Esteban Egea Lopez (Universidad Politecnica de Cartagena)
5//
6// This file is part of a software released under the license included in file
7// "license.pdf". Please read LICENSE and README files before using it.
8// The above files and the present reference are part of the software itself,
9// and cannot be removed from it.
10//
11
12#ifndef STACK_RLC_AM_BUFFER_RLCSDUSLIDINGWINDOWTRANSMISSIONBUFFER_H_
13#define STACK_RLC_AM_BUFFER_RLCSDUSLIDINGWINDOWTRANSMISSIONBUFFER_H_
14
15#include <omnetpp.h>
16#include <inet/common/packet/Packet.h>
17
18#include <algorithm>
19#include <list>
20#include <map>
21#include <set>
22
23namespace simu5g {
24
25
26
27
32 uint32_t start;
33 uint32_t end;
34
35 bool operator<(const TransmitInterval& other) const {
36 return start < other.start;
37 }
38};
39
43struct SduTxState {
44 uint32_t sn;
45 uint32_t totalLength;
46 inet::Packet *sduPointer;
47
48 // Intervals already transmitted (but not necessarily ACKed)
49 std::list<TransmitInterval> transmittedIntervals;
50 // Intervals successfully acknowledged by the peer
51 std::list<TransmitInterval> acknowledgedIntervals;
52
53 SduTxState(uint32_t s, uint32_t len, inet::Packet *ptr)
54 : sn(s), totalLength(len), sduPointer(ptr) {}
55 ~SduTxState() = default;
59 uint32_t getBytesTransmitted() const {
60 uint32_t count = 0;
61 for (const auto& interval : transmittedIntervals) {
62 count += (interval.end - interval.start + 1);
63 }
64 return count;
65 }
66
74 // Offset of the first not-yet-transmitted byte (== totalLength if fully sent).
75 uint32_t getNextByteToTx() const {
76 uint32_t nextByteToTx = 0;
77 std::list<TransmitInterval> sorted = transmittedIntervals;
78 sorted.sort();
79 for (const auto &interval : sorted) {
80 if (nextByteToTx < interval.start)
81 break;
82 nextByteToTx = interval.end + 1;
83 }
84 return nextByteToTx;
85 }
86
87 bool getNextSegment(uint32_t grantSize, uint32_t &outStart, uint32_t &outEnd) {
88 if (grantSize == 0)
89 return false;
90
91 uint32_t nextByteToTx = 0;
92 transmittedIntervals.sort();
93
94 for (const auto &interval : transmittedIntervals) {
95 if (nextByteToTx < interval.start)
96 break;
97 nextByteToTx = interval.end + 1;
98 }
99
100 if (nextByteToTx >= totalLength)
101 return false;
102
103 outStart = nextByteToTx;
104 uint32_t remainingInSdu = totalLength - nextByteToTx;
105 outEnd = outStart + std::min(grantSize, remainingInSdu) - 1;
106 return true;
107 }
111 void markTransmitted(uint32_t start, uint32_t end) {
112 transmittedIntervals.push_back({start, end});
113 mergeIntervals(transmittedIntervals);
114 }
115
116 void markAcked(uint32_t start, uint32_t end) {
117 acknowledgedIntervals.push_back({start, end});
118 mergeIntervals(acknowledgedIntervals);
119 }
120
121 bool isFullyAcked() {
122 if (acknowledgedIntervals.empty())
123 return false;
124 mergeIntervals(acknowledgedIntervals);
125 return (acknowledgedIntervals.front().start == 0 &&
126 acknowledgedIntervals.front().end == totalLength - 1);
127 }
128
129 private:
130 void mergeIntervals(std::list<TransmitInterval> &intervals) {
131 if (intervals.empty())
132 return;
133 intervals.sort();
134 for (auto it = intervals.begin(); it != intervals.end(); ) {
135 auto next = std::next(it);
136 if (next != intervals.end() && next->start <= it->end + 1) {
137 it->end = std::max(it->end, next->end);
138 intervals.erase(next);
139 }
140 else {
141 ++it;
142 }
143 }
144 }
145};
146
149// TODO: sn should use modular arithmetic (limited to 2048 for 12-bit SN or 262143 for 18-bit)
151 uint32_t sn = 0;
152 uint32_t start = 0;
153 uint32_t end = 0;
154 uint32_t totalLength = 0;
155 inet::Packet *ptr = nullptr;
156 bool isValid = false;
157};
158
159
160class RlcSduSlidingWindowTransmissionBuffer : public omnetpp::cObject
161{
162 public:
163 RlcSduSlidingWindowTransmissionBuffer(uint32_t windowSize, const std::string &name);
164 ~RlcSduSlidingWindowTransmissionBuffer() override;
165
170 virtual uint32_t addSdu(uint32_t length, inet::Packet *sduPtr);
171
177 virtual PendingSegment getSegmentForGrant(uint32_t grantSize);
178
185 virtual bool peekNextSegmentStart(uint32_t &outStart) const;
186
190 std::set<uint32_t> handleAck(uint32_t sn, uint32_t start, uint32_t end,
191 unsigned int pollSn, bool &restartPoll);
192
201 PendingSegment getRetransmissionSegment(uint32_t sn, uint32_t start,
202 uint32_t end, uint32_t grantSize);
203
205 virtual int getTotalPendingBytes() const;
206
207 bool hasUnacknowledgedData() const { return txNext_ > txNextAck_; }
208 bool windowFull() const { return txNext_ >= txNextAck_ + amWindowSize_; }
209
210 virtual bool isInRtxRange(uint32_t sn) const {
211 return hasTransmitted_ && sn >= txNextAck_ && sn <= highestSnTransmitted_;
212 }
213
214 virtual bool getSduData(uint32_t sn, inet::Packet *&outPtr, uint32_t &outTotalLen) {
215 auto it = txBuffer_.find(sn);
216 if (it == txBuffer_.end())
217 return false;
218 outPtr = it->second.sduPointer;
219 outTotalLen = it->second.totalLength;
220 return true;
221 }
222
223 virtual bool isFullyAcknowledged(uint32_t sn) {
224 auto it = txBuffer_.find(sn);
225 if (it == txBuffer_.end())
226 return false;
227 return it->second.isFullyAcked();
228 }
229
230 uint32_t getTxNext() const { return txNext_; }
231 uint32_t getTxNextAck() const { return txNextAck_; }
232 uint32_t getCurrentWindowSize() const { return txNext_ - txNextAck_; }
233 uint32_t getHighestSnTransmitted() const { return highestSnTransmitted_; }
234
235 protected:
236 std::map<uint32_t, SduTxState> txBuffer_;
237 uint32_t amWindowSize_;
238 std::string name_;
239 bool hasTransmitted_ = false;
240 uint32_t highestSnTransmitted_ = 0;
241
242 // RLC AM state variables
243 uint32_t txNext_ = 0; // Next SN to assign to a new SDU
244 uint32_t txNextAck_ = 0; // Smallest SN for which ACK is pending
245};
246
247} // namespace simu5g
248
249#endif // STACK_RLC_AM_BUFFER_RLCSDUSLIDINGWINDOWTRANSMISSIONBUFFER_H_
Definition AlertReceiver.h:24
Structure representing a specific piece of an SDU for the MAC PDU.
Definition RlcSduSlidingWindowTransmissionBuffer.h:150
uint32_t getBytesTransmitted() const
Calculates how many bytes of this specific SDU have already been transmitted.
Definition RlcSduSlidingWindowTransmissionBuffer.h:59
void markTransmitted(uint32_t start, uint32_t end)
Marks a range as transmitted.
Definition RlcSduSlidingWindowTransmissionBuffer.h:111
uint32_t getNextByteToTx() const
Finds the next available byte range that has not been transmitted.
Definition RlcSduSlidingWindowTransmissionBuffer.h:75
Represents a range of bytes [start, end] for transmission tracking.
Definition RlcSduSlidingWindowTransmissionBuffer.h:31