Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

tcp-asym.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1997 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the Daedalus Research
00017  *      Group at the University of California Berkeley.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * Contributed by the Daedalus Research Group, U.C.Berkeley
00035  * http://daedalus.cs.berkeley.edu
00036  *
00037  * @(#) $Header:
00038  */
00039 
00040 /*
00041  * tcp-asym includes modifications to several flavors of TCP to enhance
00042  * performance over asymmetric networks, where the ack channel is
00043  * constrained.  Types of asymmetry we have studied and used these mods
00044  * include bandwidth asymmetry and latency asymmetry (where  variable 
00045  * latencies cause problems to TCP, e.g., in packet radio networks.
00046  * The sender-side modifications in this file are structured as helper 
00047  * functions that are invoked from various points in the TCP code. The main
00048  * additional functionality is (a) the sender increases its congestion window
00049  * in proportion to the amount of data acked rather than the number of acks
00050  * received, (b) it breaks up potentially large bursts into smaller ones 
00051  * when acks are few and far between by rate-based pacing, and 
00052  * (c) it copies the ecn_to_echo_ bit from acks into subsequent data packets, 
00053  * using which the sink can perform ack congestion control (tcp-asym-sink.cc). 
00054  * The tcp-asym source is usually used in conjunction with a tcp-asym sink, or
00055  * with a router/end-host implementing ack filtering (semantic-packetqueue.cc).
00056  * 
00057  * For questions/comments, please contact:
00058  *   Venkata N. Padmanabhan (padmanab@cs.berkeley.edu)
00059  *   http://www.cs.berkeley.edu/~padmanab
00060  */ 
00061 
00062 #ifndef lint
00063 static const char rcsid[] =
00064     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-asym.cc,v 1.17 1999/09/09 03:22:50 salehi Exp $ (UCB)";
00065 #endif
00066 
00067 #include "tcp-asym.h"
00068 
00069 int hdr_tcpasym::offset_;
00070 
00071 static class TCPAHeaderClass : public PacketHeaderClass {
00072 public:
00073         TCPAHeaderClass() : PacketHeaderClass("PacketHeader/TCPA",
00074                                              sizeof(hdr_tcpasym)) {
00075                 bind_offset(&hdr_tcpasym::offset_);
00076         }
00077 } class_tcpahdr;
00078 
00079 static class TcpAsymClass : public TclClass {
00080 public:
00081         TcpAsymClass() : TclClass("Agent/TCP/Asym") {}
00082         TclObject* create(int, const char*const*) {
00083                 return (new TcpAsymAgent());
00084         } 
00085 } class_tcpasym;
00086 
00087 
00088 TcpAsymAgent::TcpAsymAgent() : TcpAgent(), ecn_to_echo_(0), t_exact_srtt_(0)
00089 {
00090 /*      bind("exact_srtt_", &t_exact_srtt_);*/
00091         bind("g_", &g_);
00092 /*      bind("avg_win_", &avg_win_);*/
00093 /*      bind("damp_", &damp_);*/
00094 }
00095 
00096 
00097 static class TcpRenoAsymClass : public TclClass {
00098 public:
00099         TcpRenoAsymClass() : TclClass("Agent/TCP/Reno/Asym") {}
00100         TclObject* create(int, const char*const*) {
00101                 return (new TcpRenoAsymAgent());
00102         } 
00103 } class_tcprenoasym;
00104 
00105 
00106 static class NewRenoTcpAsymClass : public TclClass {
00107 public:
00108         NewRenoTcpAsymClass() : TclClass("Agent/TCP/Newreno/Asym") {}
00109         TclObject* create(int, const char*const*) {
00110                 return (new NewRenoTcpAsymAgent());
00111         } 
00112 } class_newrenotcpasym;
00113 
00114 
00115 /* The helper functions */
00116 
00117 /* fill in the TCP asym header before packet is sent out */
00118 void TcpAsymAgent::output_helper(Packet* p) 
00119 {
00120         hdr_tcpasym *tcpha = hdr_tcpasym::access(p);
00121         hdr_flags *flagsh = hdr_flags::access(p);
00122 
00123         tcpha->win() = min(highest_ack_+window(), curseq_) - t_seqno_;
00124         tcpha->highest_ack() = highest_ack_;
00125         tcpha->max_left_to_send() = curseq_ - highest_ack_; /* XXXX not needed? */
00126 
00127         flagsh->ecnecho() = ecn_to_echo_;
00128         ecn_to_echo_ = 0;
00129 }
00130 
00131 /* schedule the next burst of data (of size at most maxburst) */
00132 void TcpAsymAgent::send_helper(int maxburst) 
00133 {
00134         /* 
00135          * If there is still data to be sent and there is space in the
00136          * window, set a timer to schedule the next burst. Note that
00137          * we wouldn't get here if TCP_TIMER_BURSTSEND were pending,
00138          * so we do not need an explicit check here.
00139          */
00140         if (t_seqno_ <= highest_ack_ + window() && t_seqno_ < curseq_) {
00141                 burstsnd_timer_.resched(t_exact_srtt_*maxburst/window());
00142         }
00143 }
00144 
00145 /* check if the received ack has an ECN that needs to be echoed back to the sink */
00146 void TcpAsymAgent::recv_helper(Packet *pkt) 
00147 {
00148         if (hdr_flags::access(pkt)->ce())
00149                 ecn_to_echo_ = 1;
00150 }
00151 
00152 /* open cwnd in proportion to the amount of data acked */
00153 void TcpAsymAgent::recv_newack_helper(Packet *pkt) 
00154 {
00155         int i;
00156         hdr_tcp *tcph = hdr_tcp::access(pkt);
00157         int ackcount = tcph->seqno() - last_ack_;
00158         double tao = Scheduler::instance().clock() - tcph->ts_echo();
00159 
00160         newack(pkt);
00161         /* update our fine-grained estimate of the smoothed RTT */
00162         if (t_exact_srtt_ != 0) 
00163                 t_exact_srtt_ = g_*tao + (1-g_)*t_exact_srtt_;
00164         else
00165                 t_exact_srtt_ = tao;
00166 /*      avg_win_ = g_*window() + (1-g_)*avg_win_;*/
00167         /* grow cwnd */
00168         for (i=0; i<ackcount; i++)
00169                 opencwnd();
00170         /* if the connection is done, call finish() */
00171         if ((highest_ack_ >= curseq_-1) && !closed_) {
00172                 closed_ = 1;
00173                 finish();
00174         }
00175 }       
00176 
00177 
00178 /* Print out if tcp-asym-specific variables have been modified */
00179 void TcpAsymAgent::traceVar(TracedVar* v) {
00180         Scheduler& s = Scheduler::instance();
00181         char wrk[500];
00182 
00183         double curtime = &s ? s.clock() : 0;
00184         if (!strcmp(v->name(), "exact_srtt_"))
00185                 sprintf(wrk,"%-8.5f %-2d %-2d %-2d %-2d %s %-6.3f", 
00186                         curtime, addr(), port(), daddr(), dport(),
00187                         v->name(), double(*((TracedDouble*) v)));
00188         else if (!strcmp(v->name(), "avg_win_"))
00189                 sprintf(wrk,"%-8.5f %-2d %-2d %-2d %-2d %s %-6.3f", 
00190                         curtime, addr(), port(), daddr(), dport(), 
00191                         v->name(), double(*((TracedDouble*) v)));
00192         else {
00193                 TcpAgent::traceVar(v);
00194                 return;
00195         }
00196 
00197         int n = strlen(wrk);
00198         wrk[n] = '\n';
00199         wrk[n+1] = 0;
00200         if (channel_)
00201                 (void)Tcl_Write(channel_, wrk, n+1);
00202         wrk[n] = 0;
00203         return;
00204 }
00205 
00206 /* Print out all the traced variables whenever any one is changed */
00207 void
00208 TcpAsymAgent::traceAll() {
00209         double curtime;
00210         Scheduler& s = Scheduler::instance();
00211         char wrk[500];
00212         int n;
00213 
00214         TcpAgent::traceAll();
00215         curtime = &s ? s.clock() : 0;
00216         sprintf(wrk, "time: %-8.5f saddr: %-2d sport: %-2d daddr: %-2d dport:"
00217                 " %-2d exact_srtt %d", curtime, addr(), port(),
00218                 daddr(), dport(), (int(t_exact_srtt_)));
00219         n = strlen(wrk);
00220         wrk[n] = '\n';
00221         wrk[n+1] = 0;
00222         if (channel_)
00223                 (void)Tcl_Write(channel_, wrk, n+1);
00224         wrk[n] = 0;
00225         return;
00226 }

Generated on Tue Apr 20 12:14:34 2004 for NS2.26SourcesOriginal by doxygen 1.3.3