PageRenderTime 53ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/INET-OverSim-20101019/src/transport/tcp/TCPSACKRexmitQueue.cc

https://bitbucket.org/indigopony/omnetproject
C++ | 365 lines | 291 code | 50 blank | 24 comment | 70 complexity | 78f74b60cb7d7c81195287d2468c29d4 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, GPL-2.0, Apache-2.0, JSON
  1. //
  2. // Copyright (C) 2009-2010 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();
  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. void TCPSACKRexmitQueue::info()
  40. {
  41. str();
  42. RexmitQueue::iterator i = rexmitQueue.begin();
  43. uint j = 1;
  44. while (i!=rexmitQueue.end())
  45. {
  46. tcpEV << j << ". region: [" << i->beginSeqNum << ".." << i->endSeqNum << ") \t sacked=" << i->sacked << "\t rexmitted=" << i->rexmitted << "\n";
  47. i++;
  48. j++;
  49. }
  50. }
  51. uint32 TCPSACKRexmitQueue::getBufferStartSeq()
  52. {
  53. return begin;
  54. }
  55. uint32 TCPSACKRexmitQueue::getBufferEndSeq()
  56. {
  57. return end;
  58. }
  59. void TCPSACKRexmitQueue::discardUpTo(uint32 seqNum)
  60. {
  61. if (rexmitQueue.empty())
  62. return;
  63. ASSERT(seqLE(begin,seqNum) && seqLE(seqNum,end));
  64. begin = seqNum;
  65. RexmitQueue::iterator i = rexmitQueue.begin();
  66. while (i!=rexmitQueue.end()) // discard/delete regions from rexmit queue, which have been acked
  67. {
  68. if (seqLess(i->beginSeqNum,begin))
  69. i = rexmitQueue.erase(i);
  70. else
  71. i++;
  72. }
  73. // update begin and end of rexmit queue
  74. if (rexmitQueue.empty())
  75. begin = end = 0;
  76. else
  77. {
  78. i = rexmitQueue.begin();
  79. begin = i->beginSeqNum;
  80. i = rexmitQueue.end();
  81. end = i->endSeqNum;
  82. }
  83. }
  84. void TCPSACKRexmitQueue::enqueueSentData(uint32 fromSeqNum, uint32 toSeqNum)
  85. {
  86. bool found = false;
  87. tcpEV << "rexmitQ: " << str() << " enqueueSentData [" << fromSeqNum << ".." << toSeqNum << ")\n";
  88. Region region;
  89. region.beginSeqNum = fromSeqNum;
  90. region.endSeqNum = toSeqNum;
  91. region.sacked = false;
  92. region.rexmitted = false;
  93. if (getQueueLength()==0)
  94. {
  95. begin = fromSeqNum;
  96. end = toSeqNum;
  97. rexmitQueue.push_back(region);
  98. // tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
  99. return;
  100. }
  101. if (seqLE(begin,fromSeqNum) && seqLE(toSeqNum,end))
  102. {
  103. // Search for region in queue!
  104. RexmitQueue::iterator i = rexmitQueue.begin();
  105. while (i!=rexmitQueue.end())
  106. {
  107. if (i->beginSeqNum == fromSeqNum && i->endSeqNum == toSeqNum)
  108. {
  109. i->rexmitted = true; // set rexmitted bit
  110. found = true;
  111. }
  112. i++;
  113. }
  114. }
  115. if (!found)
  116. {
  117. end = toSeqNum;
  118. rexmitQueue.push_back(region);
  119. }
  120. // tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
  121. }
  122. void TCPSACKRexmitQueue::setSackedBit(uint32 fromSeqNum, uint32 toSeqNum)
  123. {
  124. bool found = false;
  125. if (seqLE(toSeqNum,end))
  126. {
  127. RexmitQueue::iterator i = rexmitQueue.begin();
  128. while (i!=rexmitQueue.end())
  129. {
  130. if (i->beginSeqNum == fromSeqNum && seqGE(toSeqNum, i->endSeqNum)) // Search for LE of region in queue!
  131. {
  132. i->sacked = true; // set sacked bit
  133. found = true;
  134. i++;
  135. while (seqGE(toSeqNum, i->endSeqNum) && i!=rexmitQueue.end()) // Search for RE of region in queue!
  136. {
  137. i->sacked = true; // set sacked bit
  138. i++;
  139. }
  140. }
  141. else
  142. i++;
  143. }
  144. }
  145. if (!found)
  146. tcpEV << "FAILED to set sacked bit for region: [" << fromSeqNum << ".." << toSeqNum << "). Not found in retransmission queue.\n";
  147. }
  148. bool TCPSACKRexmitQueue::getSackedBit(uint32 seqNum)
  149. {
  150. bool found = false;
  151. if (seqLE(begin,seqNum))
  152. {
  153. RexmitQueue::iterator i = rexmitQueue.begin();
  154. while (i!=rexmitQueue.end())
  155. {
  156. if (i->beginSeqNum == seqNum) // Search for region in queue!
  157. {
  158. found = i->sacked;
  159. break;
  160. }
  161. i++;
  162. }
  163. }
  164. return found;
  165. }
  166. uint32 TCPSACKRexmitQueue::getQueueLength()
  167. {
  168. return rexmitQueue.size();
  169. }
  170. uint32 TCPSACKRexmitQueue::getHighestSackedSeqNum()
  171. {
  172. uint32 tmp_highest_sacked = 0;
  173. RexmitQueue::iterator i = rexmitQueue.begin();
  174. while (i!=rexmitQueue.end())
  175. {
  176. if (i->sacked)
  177. tmp_highest_sacked = i->endSeqNum;
  178. i++;
  179. }
  180. return tmp_highest_sacked;
  181. }
  182. uint32 TCPSACKRexmitQueue::getHighestRexmittedSeqNum()
  183. {
  184. uint32 tmp_highest_rexmitted = 0;
  185. RexmitQueue::iterator i = rexmitQueue.begin();
  186. while (i!=rexmitQueue.end())
  187. {
  188. if (i->rexmitted)
  189. tmp_highest_rexmitted = i->endSeqNum;
  190. i++;
  191. }
  192. return tmp_highest_rexmitted;
  193. }
  194. uint32 TCPSACKRexmitQueue::checkRexmitQueueForSackedOrRexmittedSegments(uint32 fromSeqNum)
  195. {
  196. uint32 counter = 0;
  197. if (fromSeqNum==0 || rexmitQueue.empty() || !(seqLE(begin,fromSeqNum) && seqLE(fromSeqNum,end)))
  198. return counter;
  199. RexmitQueue::iterator i = rexmitQueue.begin();
  200. while (i!=rexmitQueue.end())
  201. {
  202. // search for fromSeqNum (snd_nxt)
  203. if (i->beginSeqNum == fromSeqNum)
  204. break;
  205. else
  206. i++;
  207. }
  208. // search for adjacent sacked/rexmitted regions
  209. while (i!=rexmitQueue.end())
  210. {
  211. if (i->sacked || i->rexmitted)
  212. {
  213. counter = counter + (i->endSeqNum - i->beginSeqNum);
  214. // adjacent regions?
  215. uint32 tmp = i->endSeqNum;
  216. i++;
  217. if (i->beginSeqNum != tmp)
  218. break;
  219. }
  220. else
  221. break;
  222. }
  223. return counter;
  224. }
  225. void TCPSACKRexmitQueue::resetSackedBit()
  226. {
  227. RexmitQueue::iterator i = rexmitQueue.begin();
  228. while (i!=rexmitQueue.end())
  229. {
  230. i->sacked = false; // reset sacked bit
  231. i++;
  232. }
  233. }
  234. void TCPSACKRexmitQueue::resetRexmittedBit()
  235. {
  236. RexmitQueue::iterator i = rexmitQueue.begin();
  237. while (i!=rexmitQueue.end())
  238. {
  239. i->rexmitted = false; // reset rexmitted bit
  240. i++;
  241. }
  242. }
  243. uint32 TCPSACKRexmitQueue::getTotalAmountOfSackedBytes()
  244. {
  245. uint32 bytes = 0;
  246. uint32 counter = 0;
  247. RexmitQueue::iterator i = rexmitQueue.begin();
  248. while (i!=rexmitQueue.end())
  249. {
  250. if (i->sacked)
  251. {
  252. counter++;
  253. bytes = bytes + (i->endSeqNum - i->beginSeqNum);
  254. }
  255. i++;
  256. }
  257. return bytes;
  258. }
  259. uint32 TCPSACKRexmitQueue::getAmountOfSackedBytes(uint32 seqNum)
  260. {
  261. uint32 bytes = 0;
  262. uint32 counter = 0;
  263. if (rexmitQueue.empty() || seqGE(seqNum,end))
  264. return counter;
  265. RexmitQueue::iterator i = rexmitQueue.begin();
  266. while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
  267. {
  268. i++;
  269. if (i->beginSeqNum == seqNum)
  270. break;
  271. }
  272. ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
  273. while (i!=rexmitQueue.end())
  274. {
  275. if (i->sacked)
  276. {
  277. counter++;
  278. bytes = bytes + (i->endSeqNum - i->beginSeqNum);
  279. }
  280. i++;
  281. }
  282. return bytes;
  283. }
  284. uint32 TCPSACKRexmitQueue::getNumOfDiscontiguousSacks(uint32 seqNum)
  285. {
  286. uint32 counter = 0;
  287. if (rexmitQueue.empty() || seqGE(seqNum,end))
  288. return counter;
  289. RexmitQueue::iterator i = rexmitQueue.begin();
  290. while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
  291. {
  292. i++;
  293. if (i->beginSeqNum == seqNum)
  294. break;
  295. }
  296. ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
  297. // search for discontiguous sacked regions
  298. while (i!=rexmitQueue.end())
  299. {
  300. if (i->sacked)
  301. {
  302. counter++;
  303. uint32 tmp = i->endSeqNum;
  304. i++;
  305. while (i->sacked && i->beginSeqNum == tmp && i!=rexmitQueue.end()) // adjacent sacked regions?
  306. {
  307. tmp = i->endSeqNum;
  308. i++;
  309. }
  310. }
  311. else
  312. i++;
  313. }
  314. return counter;
  315. }