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 Mar 6 16:47:51 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6