INET Framework for OMNeT++/OMNEST
inet::sctp::SctpSimpleGapList Class Reference

#include <SctpGapList.h>

Public Member Functions

 SctpSimpleGapList ()
 
 ~SctpSimpleGapList ()
 
void check (const uint32_t cTsnAck) const
 
void print (std::ostream &os) const
 
uint32_t getNumGaps () const
 
uint32_t getGapStart (const uint32_t index) const
 
uint32_t getGapStop (const uint32_t index) const
 
bool tsnInGapList (const uint32_t tsn) const
 
void forwardCumAckTsn (const uint32_t cTsnAck)
 
bool tryToAdvanceCumAckTsn (uint32_t &cTsnAck)
 
void removeFromGapList (const uint32_t removedTsn)
 
bool updateGapList (const uint32_t receivedTsn, uint32_t &cTsnAck, bool &newChunkReceived)
 
void resetGaps ()
 

Private Attributes

uint32_t NumGaps
 
uint32_t GapStartList [MAX_GAP_COUNT]
 
uint32_t GapStopList [MAX_GAP_COUNT]
 

Constructor & Destructor Documentation

◆ SctpSimpleGapList()

inet::sctp::SctpSimpleGapList::SctpSimpleGapList ( )
17 {
18  NumGaps = 0;
19  for (unsigned int i = 0; i < MAX_GAP_COUNT; i++) {
20  GapStartList[i] = 0xffff00ff;
21  GapStopList[i] = 0xffff0000;
22  }
23 }

◆ ~SctpSimpleGapList()

inet::sctp::SctpSimpleGapList::~SctpSimpleGapList ( )
27 {
28 }

Member Function Documentation

◆ check()

void inet::sctp::SctpSimpleGapList::check ( const uint32_t  cTsnAck) const
32 {
33  for (uint32_t i = 0; i < NumGaps; i++) {
34  if (i == 0) {
35  assert(SctpAssociation::tsnGt(GapStartList[i], cTsnAck + 1));
36  }
37  else {
38  assert(SctpAssociation::tsnGt(GapStartList[i], GapStopList[i - 1] + 1));
39  }
41  }
42 }

Referenced by inet::sctp::SctpGapList::check().

◆ forwardCumAckTsn()

void inet::sctp::SctpSimpleGapList::forwardCumAckTsn ( const uint32_t  cTsnAck)
79 {
80  if (NumGaps > 0) {
81  // It is only possible to advance CumAckTsn when there are gaps.
82  uint32_t counter = 0;
83  uint32_t advance = 0;
84  while (counter < NumGaps) {
85  // Check whether CumAckTsn can be advanced.
86  if (SctpAssociation::tsnGe(cTsnAck, GapStartList[counter])) { // Yes!
87  advance++;
88  }
89  else { // No -> end of search.
90  break;
91  }
92  counter++;
93  }
94 
95  if (advance > 0) {
96  // We can remove "advance" block now.
97  for (uint32_t i = advance; i < NumGaps; i++) {
98  GapStartList[i - advance] = GapStartList[i];
99  GapStopList[i - advance] = GapStopList[i];
100  }
101  NumGaps -= advance;
102  }
103  }
104 }

Referenced by inet::sctp::SctpGapList::forwardCumAckTsn(), inet::sctp::SctpGapList::tryToAdvanceCumAckTsn(), and inet::sctp::SctpGapList::updateGapList().

◆ getGapStart()

uint32_t inet::sctp::SctpSimpleGapList::getGapStart ( const uint32_t  index) const
inline
37  {
38  assert(index < NumGaps);
39  return GapStartList[index];
40  }

◆ getGapStop()

uint32_t inet::sctp::SctpSimpleGapList::getGapStop ( const uint32_t  index) const
inline
43  {
44  assert(index < NumGaps);
45  return GapStopList[index];
46  }

◆ getNumGaps()

uint32_t inet::sctp::SctpSimpleGapList::getNumGaps ( ) const
inline
32  {
33  return NumGaps;
34  }

◆ print()

void inet::sctp::SctpSimpleGapList::print ( std::ostream &  os) const
55 {
56  os << "{";
57  for (uint32_t i = 0; i < NumGaps; i++) {
58  if (i > 0) {
59  os << ",";
60  }
61  os << " " << GapStartList[i] << "-" << GapStopList[i];
62  }
63  os << " }";
64 }

Referenced by inet::sctp::operator<<().

◆ removeFromGapList()

void inet::sctp::SctpSimpleGapList::removeFromGapList ( const uint32_t  removedTsn)
132 {
133  const int32_t initialNumGaps = NumGaps;
134 
135  for (int32_t i = initialNumGaps - 1; i >= 0; i--) {
136  if (SctpAssociation::tsnBetween(GapStartList[i], removedTsn, GapStopList[i])) {
137  // ====== Gap block contains more than one TSN =====================
138  const int32_t gapsize = (int32_t)(GapStopList[i] - GapStartList[i] + 1);
139  if (gapsize > 1) {
140  if (GapStopList[i] == removedTsn) { // Remove stop TSN
141  GapStopList[i]--;
142  }
143  else if (GapStartList[i] == removedTsn) { // Remove start TSN
144  GapStartList[i]++;
145  }
146  else { // Block has to be splitted up
147  NumGaps = std::min(NumGaps + 1, (uint32_t)MAX_GAP_COUNT); // Enforce upper limit!
148  for (int32_t j = NumGaps - 1; j > i; j--) {
149  GapStopList[j] = GapStopList[j - 1];
150  GapStartList[j] = GapStartList[j - 1];
151  }
152  GapStopList[i] = removedTsn - 1;
153  if ((uint32_t)i + 1 < NumGaps) {
154  GapStartList[i + 1] = removedTsn + 1;
155  }
156  }
157  }
158  // ====== Just a single TSN in the gap block (start==stop) =========
159  else {
160  for (int32_t j = i; j <= initialNumGaps - 1; j++) {
161  GapStopList[j] = GapStopList[j + 1];
162  GapStartList[j] = GapStartList[j + 1];
163  }
164  GapStartList[initialNumGaps - 1] = 0;
165  GapStopList[initialNumGaps - 1] = 0;
166  NumGaps--;
167  }
168 
169  break; // TSN removed -> done!
170  }
171  }
172 }

Referenced by inet::sctp::SctpGapList::removeFromGapList(), and inet::sctp::SctpGapList::updateGapList().

◆ resetGaps()

void inet::sctp::SctpSimpleGapList::resetGaps ( )
45 {
46  NumGaps = 0;
47  for (unsigned int i = 0; i < MAX_GAP_COUNT; i++) {
48  GapStartList[i] = 0xffff00ff;
49  GapStopList[i] = 0xffff0000;
50  }
51 }

Referenced by inet::sctp::SctpGapList::resetGaps().

◆ tryToAdvanceCumAckTsn()

bool inet::sctp::SctpSimpleGapList::tryToAdvanceCumAckTsn ( uint32_t &  cTsnAck)
108 {
109  bool progress = false;
110  if (NumGaps > 0) {
111  // It is only possible to advance CumAckTsn when there are gaps.
112  uint32_t counter = 0;
113  while (counter < NumGaps) {
114  // Check whether CumAckTsn can be advanced.
115  if (cTsnAck + 1 == GapStartList[0]) { // Yes!
116  cTsnAck = GapStopList[0];
117  // We can take out all fragments of this block
118  for (uint32_t i = 1; i < NumGaps; i++) {
119  GapStartList[i - 1] = GapStartList[i];
120  GapStopList[i - 1] = GapStopList[i];
121  }
122  progress = true;
123  }
124  counter++;
125  }
126  }
127  return progress;
128 }

Referenced by inet::sctp::SctpGapList::tryToAdvanceCumAckTsn().

◆ tsnInGapList()

bool inet::sctp::SctpSimpleGapList::tsnInGapList ( const uint32_t  tsn) const
68 {
69  for (uint32_t i = 0; i < NumGaps; i++) {
71  return true;
72  }
73  }
74  return false;
75 }

◆ updateGapList()

bool inet::sctp::SctpSimpleGapList::updateGapList ( const uint32_t  receivedTsn,
uint32_t &  cTsnAck,
bool &  newChunkReceived 
)

TSN either sits at the end of one gap, and thus changes gap boundaries, or it is in between two gaps, and becomes a new gap

178 {
179  if (SctpAssociation::tsnLe(receivedTsn, cTsnAck)) {
180  // Received TSN covered by CumAckTSN -> nothing to do.
181  return false;
182  }
183 
184  uint32_t lo = cTsnAck + 1;
185  for (uint32_t i = 0; i < NumGaps; i++) {
186  if (GapStartList[i] > 0) {
187  const uint32_t hi = GapStartList[i] - 1;
188  if (SctpAssociation::tsnBetween(lo, receivedTsn, hi)) {
189  const uint32_t gapsize = hi - lo + 1;
190  if (gapsize > 1) {
195  if (receivedTsn == hi) {
196  GapStartList[i] = receivedTsn;
197  newChunkReceived = true;
198  return true;
199  }
200  else if (receivedTsn == lo) {
201  if (receivedTsn == (cTsnAck + 1)) {
202  cTsnAck++;
203  newChunkReceived = true;
204  return true;
205  }
206  /* some gap must increase its upper bound */
207  GapStopList[i - 1] = receivedTsn;
208  newChunkReceived = true;
209  return true;
210  }
211  else { /* a gap in between */
212  NumGaps = std::min(NumGaps + 1, (uint32_t)MAX_GAP_COUNT); // Enforce upper limit!
213 
214  for (uint32_t j = NumGaps - 1; j > i; j--) {
215  GapStartList[j] = GapStartList[j - 1];
216  GapStopList[j] = GapStopList[j - 1];
217  }
218  GapStartList[i] = receivedTsn;
219  GapStopList[i] = receivedTsn;
220  newChunkReceived = true;
221  return true;
222  }
223  }
224  else { /* alright: gapsize is 1: our received tsn may close gap between fragments */
225  if (lo == cTsnAck + 1) {
226  cTsnAck = GapStopList[i];
227  if (i == NumGaps - 1) {
228  GapStartList[i] = 0;
229  GapStopList[i] = 0;
230  }
231  else {
232  for (uint32_t j = i; j < NumGaps - 1; j++) {
233  GapStartList[j] = GapStartList[j + 1];
234  GapStopList[j] = GapStopList[j + 1];
235  }
236  }
237  NumGaps--;
238  newChunkReceived = true;
239  return true;
240  }
241  else {
242  GapStopList[i - 1] = GapStopList[i];
243  if (i == NumGaps - 1) {
244  GapStartList[i] = 0;
245  GapStopList[i] = 0;
246  }
247  else {
248  for (uint32_t j = i; j < NumGaps - 1; j++) {
249  GapStartList[j] = GapStartList[j + 1];
250  GapStopList[j] = GapStopList[j + 1];
251  }
252  }
253  NumGaps--;
254  newChunkReceived = true;
255  return true;
256  }
257  }
258  }
259  else { /* receivedTsn is not in the gap between these fragments... */
260  lo = GapStopList[i] + 1;
261  }
262  } /* end: for */
263  } /* end: for */
264 
265  // ====== We have reached the end of the list ============================
266  if (receivedTsn == lo) { // just increase CumAckTsn, handle further update of CumAckTsn later
267  if (receivedTsn == cTsnAck + 1) {
268  cTsnAck = receivedTsn;
269  newChunkReceived = true;
270  return true;
271  }
272  // Update last fragment, stop TSN by one.
273  GapStopList[NumGaps - 1]++;
274 
275  newChunkReceived = true;
276  return true;
277  }
278  else {
279  // If the received TSN is new, the list is either empty or the received
280  // TSN is larger than the last gap end + 1. Otherwise, the TSN has already
281  // been acknowledged.
282  if ((NumGaps == 0) ||
283  (SctpAssociation::tsnGt(receivedTsn, GapStopList[NumGaps - 1] + 1)))
284  {
285  // A new fragment altogether, past the end of the list
286  if (NumGaps < MAX_GAP_COUNT) { // T.D. 18.12.09: Enforce upper limit!
287  GapStartList[NumGaps] = receivedTsn;
288  GapStopList[NumGaps] = receivedTsn;
289  NumGaps++;
290  newChunkReceived = true;
291  }
292  }
293  return true;
294  }
295 
296  return false;
297 }

Referenced by inet::sctp::SctpGapList::updateGapList().

Member Data Documentation

◆ GapStartList

uint32_t inet::sctp::SctpSimpleGapList::GapStartList[MAX_GAP_COUNT]
private

◆ GapStopList

uint32_t inet::sctp::SctpSimpleGapList::GapStopList[MAX_GAP_COUNT]
private

◆ NumGaps

uint32_t inet::sctp::SctpSimpleGapList::NumGaps
private

The documentation for this class was generated from the following files:
inet::sctp::SctpAssociation::tsnBetween
static bool tsnBetween(const uint32_t tsn1, const uint32_t midtsn, const uint32_t tsn2)
Definition: SctpAssociation.h:1079
inet::sctp::SctpAssociation::tsnGt
static bool tsnGt(const uint32_t tsn1, const uint32_t tsn2)
Definition: SctpAssociation.h:1076
inet::sctp::SctpSimpleGapList::GapStartList
uint32_t GapStartList[MAX_GAP_COUNT]
Definition: SctpGapList.h:61
MAX_GAP_COUNT
#define MAX_GAP_COUNT
Definition: SctpGapList.h:20
inet::sctp::min
double min(const double a, const double b)
Returns the minimum of a and b.
Definition: SctpAssociation.h:261
inet::sctp::SctpAssociation::tsnGe
static bool tsnGe(const uint32_t tsn1, const uint32_t tsn2)
Definition: SctpAssociation.h:1075
inet::sctp::SctpSimpleGapList::NumGaps
uint32_t NumGaps
Definition: SctpGapList.h:60
inet::sctp::SctpSimpleGapList::GapStopList
uint32_t GapStopList[MAX_GAP_COUNT]
Definition: SctpGapList.h:62
inet::sctp::SctpAssociation::tsnLe
static bool tsnLe(const uint32_t tsn1, const uint32_t tsn2)
Definition: SctpAssociation.h:1077