tcp-reno.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:6k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1990, 1997 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted
  7.  * provided that the above copyright notice and this paragraph are
  8.  * duplicated in all such forms and that any documentation,
  9.  * advertising materials, and other materials related to such
  10.  * distribution and use acknowledge that the software was developed
  11.  * by the University of California, Lawrence Berkeley Laboratory,
  12.  * Berkeley, CA.  The name of the University may not be used to
  13.  * endorse or promote products derived from this software without
  14.  * specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19. #ifndef lint
  20. static const char rcsid[] =
  21.     "@(#) $Header: /cvsroot/nsnam/ns-2/tcp/tcp-reno.cc,v 1.43 2006/06/14 18:05:30 sallyfloyd Exp $ (LBL)";
  22. #endif
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <sys/types.h>
  26. #include "ip.h"
  27. #include "tcp.h"
  28. #include "flags.h"
  29. static class RenoTcpClass : public TclClass {
  30. public:
  31. RenoTcpClass() : TclClass("Agent/TCP/Reno") {}
  32. TclObject* create(int, const char*const*) {
  33. return (new RenoTcpAgent());
  34. }
  35. } class_reno;
  36. int RenoTcpAgent::window()
  37. {
  38. //
  39. // reno: inflate the window by dupwnd_
  40. // dupwnd_ will be non-zero during fast recovery,
  41. // at which time it contains the number of dup acks
  42. //
  43. int win = int(cwnd_) + dupwnd_;
  44. if (frto_ == 2) {
  45. // First ack after RTO has arrived.
  46. // Open window to allow two new segments out with F-RTO.
  47. win = force_wnd(2);
  48. }
  49. if (win > int(wnd_))
  50. win = int(wnd_);
  51. return (win);
  52. }
  53. double RenoTcpAgent::windowd()
  54. {
  55. //
  56. // reno: inflate the window by dupwnd_
  57. // dupwnd_ will be non-zero during fast recovery,
  58. // at which time it contains the number of dup acks
  59. //
  60. double win = cwnd_ + dupwnd_;
  61. if (win > wnd_)
  62. win = wnd_;
  63. return (win);
  64. }
  65. RenoTcpAgent::RenoTcpAgent() : TcpAgent(), dupwnd_(0)
  66. {
  67. }
  68. void RenoTcpAgent::recv(Packet *pkt, Handler*)
  69. {
  70. hdr_tcp *tcph = hdr_tcp::access(pkt);
  71. int valid_ack = 0;
  72.         if (qs_approved_ == 1 && tcph->seqno() > last_ack_)
  73. endQuickStart();
  74.         if (qs_requested_ == 1)
  75.                 processQuickStart(pkt);
  76. #ifdef notdef
  77. if (pkt->type_ != PT_ACK) {
  78. fprintf(stderr,
  79. "ns: confiuration error: tcp received non-ackn");
  80. exit(1);
  81. }
  82. #endif
  83.         /* W.N.: check if this is from a previous incarnation */
  84.         if (tcph->ts() < lastreset_) {
  85.                 // Remove packet and do nothing
  86.                 Packet::free(pkt);
  87.                 return;
  88.         }
  89. ++nackpack_;
  90. ts_peer_ = tcph->ts();
  91. if (hdr_flags::access(pkt)->ecnecho() && ecn_)
  92. ecn(tcph->seqno());
  93. recv_helper(pkt);
  94. recv_frto_helper(pkt);
  95. if (tcph->seqno() > last_ack_) {
  96. if (last_cwnd_action_ == CWND_ACTION_DUPACK)
  97. last_cwnd_action_ = CWND_ACTION_EXITED;
  98. dupwnd_ = 0;
  99. recv_newack_helper(pkt);
  100. if (last_ack_ == 0 && delay_growth_) {
  101. cwnd_ = initial_window();
  102. }
  103. } else if (tcph->seqno() == last_ack_) {
  104. if (hdr_flags::access(pkt)->eln_ && eln_) {
  105. tcp_eln(pkt);
  106. return;
  107. }
  108. if (++dupacks_ == numdupacks_) {
  109. dupack_action();
  110. if (!exitFastRetrans_)
  111. dupwnd_ = numdupacks_;
  112. } else if (dupacks_ > numdupacks_ && (!exitFastRetrans_ 
  113.      || last_cwnd_action_ == CWND_ACTION_DUPACK )) {
  114. ++dupwnd_; // fast recovery
  115. } else if (dupacks_ < numdupacks_ && singledup_ ) {
  116. send_one();
  117. }
  118. }
  119.         if (tcph->seqno() >= last_ack_)
  120.                 // Check if ACK is valid.  Suggestion by Mark Allman.
  121.                 valid_ack = 1;
  122. Packet::free(pkt);
  123. #ifdef notyet
  124. if (trace_)
  125. plot();
  126. #endif
  127. /*
  128.  * Try to send more data
  129.  */
  130.         if (valid_ack || aggressive_maxburst_)
  131. if (dupacks_ == 0 || dupacks_ > numdupacks_ - 1)
  132. send_much(0, 0, maxburst_);
  133. }
  134. int
  135. RenoTcpAgent::allow_fast_retransmit(int last_cwnd_action_)
  136. {
  137. return (last_cwnd_action_ == CWND_ACTION_DUPACK);
  138. }
  139. /*
  140.  * Dupack-action: what to do on a DUP ACK.  After the initial check
  141.  * of 'recover' below, this function implements the following truth
  142.  * table:
  143.  *  
  144.  *      bugfix  ecn     last-cwnd == ecn        action  
  145.  *  
  146.  *      0       0       0                       reno_action
  147.  *      0       0       1                       reno_action    [impossible]
  148.  *      0       1       0                       reno_action
  149.  *      0       1       1                       retransmit, return  
  150.  *      1       0       0                       nothing 
  151.  *      1       0       1                       nothing        [impossible]
  152.  *      1       1       0                       nothing 
  153.  *      1       1       1                       retransmit, return
  154.  */ 
  155.     
  156. void
  157. RenoTcpAgent::dupack_action()
  158. {
  159. int recovered = (highest_ack_ > recover_);
  160. int allowFastRetransmit = allow_fast_retransmit(last_cwnd_action_);
  161.         if (recovered || (!bug_fix_ && !ecn_) || allowFastRetransmit 
  162. || (bugfix_ss_ && highest_ack_ == 0)) {
  163.                 // (highest_ack_ == 0) added to allow Fast Retransmit
  164.                 //  when the first data packet is dropped.
  165.                 //  From bugreport from Mark Allman.
  166. goto reno_action;
  167. }
  168. if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
  169. last_cwnd_action_ = CWND_ACTION_DUPACK;
  170. /* 
  171.  * What if there is a DUPACK action followed closely by ECN
  172.  * followed closely by a DUPACK action?
  173.  * The optimal thing to do would be to remember all
  174.  * congestion actions from the most recent window
  175.  * of data.  Otherwise "bugfix" might not prevent
  176.  * all unnecessary Fast Retransmits.
  177.  */
  178. reset_rtx_timer(1,0);
  179. output(last_ack_ + 1, TCP_REASON_DUPACK);
  180. dupwnd_ = numdupacks_;
  181. return; 
  182. }
  183. if (bug_fix_) {
  184. /*
  185.  * The line below, for "bug_fix_" true, avoids
  186.  * problems with multiple fast retransmits in one
  187.  * window of data.
  188.  */
  189. return;
  190. }
  191. reno_action:
  192. // we are now going to fast-retransmit and will trace that event
  193. trace_event("RENO_FAST_RETX");
  194. recover_ = maxseq_;
  195. last_cwnd_action_ = CWND_ACTION_DUPACK;
  196. slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
  197. reset_rtx_timer(1,0);
  198. output(last_ack_ + 1, TCP_REASON_DUPACK); // from top
  199.         dupwnd_ = numdupacks_;
  200. return;
  201. }
  202. void RenoTcpAgent::timeout(int tno)
  203. {
  204. if (tno == TCP_TIMER_RTX) {
  205. dupwnd_ = 0;
  206. dupacks_ = 0;
  207. if (bug_fix_) recover_ = maxseq_;
  208. TcpAgent::timeout(tno);
  209. } else {
  210. timeout_nonrtx(tno);
  211. }
  212. }