PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/transport/tcp/TCPSACKRexmitQueue.cc

https://github.com/Sorouri/inetmanet
C++ | 341 lines | 270 code | 49 blank | 22 comment | 69 complexity | 500664eb9a7a41d8ff9b08456fca04df MD5 | raw file
Possible License(s): GPL-2.0
  1. //
  2. // Copyright (C) 2009 Thomas Reschka
  3. //
  4. // This program is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public License
  6. // as published by the Free Software Foundation; either version 2
  7. // of the License, or (at your option) any later version.
  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 Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with this program; if not, see <http://www.gnu.org/licenses/>.
  16. //
  17. #include "TCPSACKRexmitQueue.h"
  18. TCPSACKRexmitQueue::TCPSACKRexmitQueue()
  19. {
  20. conn = NULL;
  21. begin = end = 0;
  22. }
  23. TCPSACKRexmitQueue::~TCPSACKRexmitQueue()
  24. {
  25. while (!rexmitQueue.empty())
  26. rexmitQueue.pop_front(); // TODO rexmit warnings (delete operator) are still present
  27. }
  28. void TCPSACKRexmitQueue::init(uint32 seqNum)
  29. {
  30. begin = seqNum;
  31. end = seqNum;
  32. }
  33. std::string TCPSACKRexmitQueue::str() const
  34. {
  35. std::stringstream out;
  36. out << "[" << begin << ".." << end << ")";
  37. return out.str();
  38. }
  39. uint32 TCPSACKRexmitQueue::getBufferEndSeq()
  40. {
  41. return end;
  42. }
  43. void TCPSACKRexmitQueue::discardUpTo(uint32 seqNum)
  44. {
  45. if (rexmitQueue.empty())
  46. return;
  47. ASSERT(seqLE(begin,seqNum) && seqLE(seqNum,end));
  48. begin = seqNum;
  49. RexmitQueue::iterator i = rexmitQueue.begin();
  50. while (i!=rexmitQueue.end()) // discard/delete regions from rexmit queue, which have been acked
  51. {
  52. if (seqLess(i->beginSeqNum,begin))
  53. i = rexmitQueue.erase(i);
  54. else
  55. i++;
  56. }
  57. // update begin and end of rexmit queue
  58. if (rexmitQueue.empty())
  59. begin = end = 0;
  60. else
  61. {
  62. i = rexmitQueue.begin();
  63. begin = i->beginSeqNum;
  64. i = rexmitQueue.end();
  65. end = i->endSeqNum;
  66. }
  67. }
  68. void TCPSACKRexmitQueue::enqueueSentData(uint32 fromSeqNum, uint32 toSeqNum)
  69. {
  70. bool found = false;
  71. tcpEV << "rexmitQ: " << str() << " enqueueSentData [" << fromSeqNum << ".." << toSeqNum << ")\n";
  72. Region region;
  73. region.beginSeqNum = fromSeqNum;
  74. region.endSeqNum = toSeqNum;
  75. region.sacked = false;
  76. region.rexmitted = false;
  77. if (getQueueLength()==0)
  78. {
  79. begin = fromSeqNum;
  80. end = toSeqNum;
  81. rexmitQueue.push_back(region);
  82. tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
  83. return;
  84. }
  85. if (seqLE(begin,fromSeqNum) && seqLE(toSeqNum,end))
  86. {
  87. // Search for region in queue!
  88. RexmitQueue::iterator i = rexmitQueue.begin();
  89. while (i!=rexmitQueue.end())
  90. {
  91. if (i->beginSeqNum == fromSeqNum && i->endSeqNum == toSeqNum)
  92. {
  93. i->rexmitted=true; // set rexmitted bit
  94. found = true;
  95. }
  96. i++;
  97. }
  98. }
  99. if (!found)
  100. {
  101. end = toSeqNum;
  102. rexmitQueue.push_back(region);
  103. }
  104. tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
  105. }
  106. void TCPSACKRexmitQueue::setSackedBit(uint32 fromSeqNum, uint32 toSeqNum)
  107. {
  108. bool found = false;
  109. if (seqLE(begin,fromSeqNum) && seqLE(toSeqNum,end))
  110. {
  111. RexmitQueue::iterator i = rexmitQueue.begin();
  112. while (i!=rexmitQueue.end())
  113. {
  114. if (i->beginSeqNum == fromSeqNum && i->endSeqNum == toSeqNum) // Search for region in queue!
  115. {
  116. i->sacked=true; // set sacked bit
  117. found = true;
  118. }
  119. i++;
  120. }
  121. }
  122. if (!found)
  123. tcpEV << "FAILED to set sacked bit for region: [" << fromSeqNum << ".." << toSeqNum << "). Not found in retransmission queue.\n";
  124. }
  125. bool TCPSACKRexmitQueue::getSackedBit(uint32 seqNum)
  126. {
  127. bool found = false;
  128. if (seqLE(begin,seqNum))
  129. {
  130. RexmitQueue::iterator i = rexmitQueue.begin();
  131. while (i!=rexmitQueue.end())
  132. {
  133. if (i->beginSeqNum == seqNum) // Search for region in queue!
  134. {
  135. found = i->sacked;
  136. break;
  137. }
  138. i++;
  139. }
  140. }
  141. return found;
  142. }
  143. uint32 TCPSACKRexmitQueue::getQueueLength()
  144. {
  145. return rexmitQueue.size();
  146. }
  147. uint32 TCPSACKRexmitQueue::getHighestSackedSeqNum()
  148. {
  149. uint32 tmp_highest_sacked = 0;
  150. RexmitQueue::iterator i = rexmitQueue.begin();
  151. while (i!=rexmitQueue.end())
  152. {
  153. if (i->sacked)
  154. tmp_highest_sacked = i->endSeqNum;
  155. i++;
  156. }
  157. return tmp_highest_sacked;
  158. }
  159. uint32 TCPSACKRexmitQueue::getHighestRexmittedSeqNum()
  160. {
  161. uint32 tmp_highest_rexmitted = 0;
  162. RexmitQueue::iterator i = rexmitQueue.begin();
  163. while (i!=rexmitQueue.end())
  164. {
  165. if (i->rexmitted)
  166. tmp_highest_rexmitted = i->endSeqNum;
  167. i++;
  168. }
  169. return tmp_highest_rexmitted;
  170. }
  171. uint32 TCPSACKRexmitQueue::checkRexmitQueueForSackedOrRexmittedSegments(uint32 fromSeqNum)
  172. {
  173. uint32 counter = 0;
  174. if (fromSeqNum==0 || rexmitQueue.empty() || !(seqLE(begin,fromSeqNum) && seqLE(fromSeqNum,end)))
  175. return counter;
  176. RexmitQueue::iterator i = rexmitQueue.begin();
  177. while (i!=rexmitQueue.end())
  178. {
  179. // search for fromSeqNum (snd_nxt)
  180. if (i->beginSeqNum == fromSeqNum)
  181. break;
  182. else
  183. i++;
  184. }
  185. // search for adjacent sacked/rexmitted regions
  186. while (i!=rexmitQueue.end())
  187. {
  188. if (i->sacked || i->rexmitted)
  189. {
  190. counter = counter + (i->endSeqNum - i->beginSeqNum);
  191. // adjacent regions?
  192. uint32 tmp = i->endSeqNum;
  193. i++;
  194. if (i->beginSeqNum != tmp)
  195. break;
  196. }
  197. else
  198. break;
  199. }
  200. return counter;
  201. }
  202. void TCPSACKRexmitQueue::resetSackedBit()
  203. {
  204. RexmitQueue::iterator i = rexmitQueue.begin();
  205. while (i!=rexmitQueue.end())
  206. {
  207. i->sacked=false; // reset sacked bit
  208. i++;
  209. }
  210. }
  211. void TCPSACKRexmitQueue::resetRexmittedBit()
  212. {
  213. RexmitQueue::iterator i = rexmitQueue.begin();
  214. while (i!=rexmitQueue.end())
  215. {
  216. i->rexmitted=false; // reset rexmitted bit
  217. i++;
  218. }
  219. }
  220. uint32 TCPSACKRexmitQueue::getTotalAmountOfSackedBytes()
  221. {
  222. uint32 bytes = 0;
  223. uint32 counter = 0;
  224. RexmitQueue::iterator i = rexmitQueue.begin();
  225. while (i!=rexmitQueue.end())
  226. {
  227. if (i->sacked)
  228. {
  229. counter++;
  230. bytes = bytes + (i->endSeqNum - i->beginSeqNum);
  231. }
  232. i++;
  233. }
  234. return bytes;
  235. }
  236. uint32 TCPSACKRexmitQueue::getAmountOfSackedBytes(uint32 seqNum)
  237. {
  238. uint32 bytes = 0;
  239. uint32 counter = 0;
  240. if (rexmitQueue.empty() || seqGE(seqNum,end))
  241. return counter;
  242. RexmitQueue::iterator i = rexmitQueue.begin();
  243. while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
  244. {
  245. i++;
  246. if (i->beginSeqNum == seqNum)
  247. break;
  248. }
  249. ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
  250. while (i!=rexmitQueue.end())
  251. {
  252. if (i->sacked)
  253. {
  254. counter++;
  255. bytes = bytes + (i->endSeqNum - i->beginSeqNum);
  256. }
  257. i++;
  258. }
  259. return bytes;
  260. }
  261. uint32 TCPSACKRexmitQueue::getNumOfDiscontiguousSacks(uint32 seqNum)
  262. {
  263. uint32 counter = 0;
  264. if (rexmitQueue.empty() || seqGE(seqNum,end))
  265. return counter;
  266. RexmitQueue::iterator i = rexmitQueue.begin();
  267. while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
  268. {
  269. i++;
  270. if (i->beginSeqNum == seqNum)
  271. break;
  272. }
  273. ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
  274. // search for discontiguous sacked regions
  275. while (i!=rexmitQueue.end())
  276. {
  277. if (i->sacked)
  278. {
  279. counter++;
  280. uint32 tmp = i->endSeqNum;
  281. i++;
  282. while (i->sacked && i->beginSeqNum == tmp && i!=rexmitQueue.end()) // adjacent sacked regions?
  283. {
  284. tmp = i->endSeqNum;
  285. i++;
  286. }
  287. }
  288. else
  289. i++;
  290. }
  291. return counter;
  292. }