?? tcp-session.cc
字號:
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 1997 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Daedalus Research * Group at the University of California Berkeley. * 4. Neither the name of the University nor of the Research Group may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-session.cc,v 1.18 2000/09/01 03:04:07 haoboy Exp $ */#include <stdlib.h>#include <math.h>#include "ip.h"#include "flags.h"#include "random.h"#include "template.h"#include "nilist.h"#include "tcp.h"#include "tcp-int.h"#include "tcp-session.h"/* * We separate TCP functionality into two parts: that having to do with * providing a reliable, ordered byte-stream service, and that having to do with * congestion control and loss recovery. The former is done on a per-connection * basis and is implemented as part of IntTcpAgent ("integrated TCP"). The * latter is done in an integrated fashion across multiple TCP connections, and * is implemented as part of TcpSessionAgent ("TCP session"). TcpSessionAgent is * derived from CorresHost ("correspondent host"), which keeps track of the * state of all TCP (TCP/Int) connections to a host that it is corresponding * with. * * The motivation for this separation of functionality is to make an ensemble of * connection more well-behaved than a set of independent TCP connections. * The packet loss rate is cut down and the chances of losses being recovered * via data-driven techniques (rather than via timeouts) is improved. At the * same time, we do not introduce any unnecessary coupling between the * logically-independent byte-streams that the set of connections represents. * This is in contrast to the coupling that is inherent in the multiplexing at * the application layer of multiple byte-streams onto a single TCP connection. * * For questions/comments, please contact: * Venkata N. Padmanabhan (padmanab@cs.berkeley.edu) * http://www.cs.berkeley.edu/~padmanab */static class TcpSessionClass : public TclClass {public: TcpSessionClass() : TclClass("Agent/TCP/Session") {} TclObject* create(int, const char*const*) { return (new TcpSessionAgent()); }} class_tcpsession;TcpSessionAgent::TcpSessionAgent() : CorresHost(), rtx_timer_(this), burstsnd_timer_(this), sessionSeqno_(0), last_send_time_(-1), curConn_(0), numConsecSegs_(0), schedDisp_(FINE_ROUND_ROBIN), wtSum_(0), dynWtSum_(0) { bind("ownd_", &ownd_); bind("owndCorr_", &owndCorrection_); bind_bool("proxyopt_", &proxyopt_); bind_bool("fixedIw_", &fixedIw_); bind("schedDisp_", &schedDisp_); bind_bool("disableIntLossRecov_", &disableIntLossRecov_); sessionList_.append(this);}intTcpSessionAgent::command(int argc, const char*const* argv){ if (argc == 2) { if (!strcmp(argv[1], "resetwt")) { Islist_iter<IntTcpAgent> conn_iter(conns_); IntTcpAgent *tcp; while ((tcp = conn_iter()) != NULL) tcp->wt_ = 1; wtSum_ = conn_iter.count(); return (TCL_OK); } } return (CorresHost::command(argc, argv));}voidSessionRtxTimer::expire(Event*){ a_->timeout(TCP_TIMER_RTX);}voidSessionResetTimer::expire(Event*){ a_->timeout(TCP_TIMER_RESET);}voidSessionBurstSndTimer::expire(Event*){ a_->timeout(TCP_TIMER_BURSTSND);}voidTcpSessionAgent::reset_rtx_timer(int /*mild*/, int backoff){ if (backoff) rtt_backoff(); set_rtx_timer(); rtt_active_ = 0;}voidTcpSessionAgent::set_rtx_timer(){ if (rtx_timer_.status() == TIMER_PENDING) rtx_timer_.cancel(); if (reset_timer_.status() == TIMER_PENDING) reset_timer_.cancel(); if (fs_enable_ && fs_mode_) reset_timer_.resched(rtt_exact_timeout()); else rtx_timer_.resched(rtt_timeout());}voidTcpSessionAgent::cancel_rtx_timer(){ rtx_timer_.force_cancel(); reset_timer_.force_cancel();}voidTcpSessionAgent::cancel_timers(){ rtx_timer_.force_cancel(); reset_timer_.force_cancel(); burstsnd_timer_.force_cancel(); delsnd_timer_.force_cancel();}intTcpSessionAgent::fs_pkt() { return (fs_enable_ && fs_mode_ && sessionSeqno_-1 >= fs_startseq_ && sessionSeqno_-1 < fs_endseq_);}voidTcpSessionAgent::rtt_update_exact(double tao){ double g = 1/8; /* gain used for smoothing rtt */ double h = 1/4; /* gain used for smoothing rttvar */ double delta; if (t_exact_srtt_ != 0) { delta = tao - t_exact_srtt_; if (delta < 0) delta = -delta; /* update the fine-grained estimate of the smoothed RTT */ if (t_exact_srtt_ != 0) t_exact_srtt_ = g*tao + (1-g)*t_exact_srtt_; else t_exact_srtt_ = tao; /* update the fine-grained estimate of mean deviation in RTT */ delta -= t_exact_rttvar_; t_exact_rttvar_ += h*delta; } else { t_exact_srtt_ = tao; t_exact_rttvar_ = tao/2; }} voidTcpSessionAgent::newack(Packet *pkt) { double now = Scheduler::instance().clock(); Islist_iter<Segment> seg_iter(seglist_); hdr_tcp *tcph = hdr_tcp::access(pkt); hdr_flags *fh = hdr_flags::access(pkt); if (!fh->no_ts_) { /* if the timestamp option is being used */ if (ts_option_) { rtt_update(now - tcph->ts_echo()); rtt_update_exact(now - tcph->ts_echo()); } /* if segment being timed just got acked */ if (rtt_active_ && rtt_seg_ == NULL) { t_backoff_ = 1; rtt_active_ = 0; if (!ts_option_) rtt_update(now - rtt_ts_); } } if (seg_iter.count() > 0) set_rtx_timer(); else cancel_rtx_timer();}voidTcpSessionAgent::timeout(int tno){ if (tno == TCP_TIMER_BURSTSND) send_much(NULL,0,0); else if (tno == TCP_TIMER_RESET) { Islist_iter<Segment> seg_iter(seglist_); Segment *curseg; Islist_iter<IntTcpAgent> conn_iter(conns_); IntTcpAgent *curconn; fs_mode_ = 0; if (seg_iter.count() == 0 && !slow_start_restart_) { return; } recover_ = sessionSeqno_ - 1; last_cwnd_action_ = CWND_ACTION_TIMEOUT; ownd_ = 0; owndCorrection_ = 0; while ((curconn = conn_iter()) != NULL) { curconn->maxseq_ = curconn->highest_ack_; curconn->t_seqno_ = curconn->highest_ack_ + 1; curconn->recover_ = curconn->maxseq_; curconn->last_cwnd_action_ = CWND_ACTION_TIMEOUT; } while ((curseg = seg_iter()) != NULL) { /* XXX exclude packets sent "recently"? */ curseg->size_ = 0; } /* * If first pkt sent before fast start has not gotten through, * treat this as a regular rtx timeout. Otherwise, close cwnd * and reset timer but don't back off timer. */ if (connWithPktBeforeFS_) { connWithPktBeforeFS_ = NULL; timeout(TCP_TIMER_RTX); } else { slowdown(CLOSE_CWND_INIT); reset_rtx_timer(0,0); send_much(NULL, 0, TCP_REASON_TIMEOUT); } } else if (tno == TCP_TIMER_RTX) { Islist_iter<Segment> seg_iter(seglist_); Segment *curseg; Islist_iter<IntTcpAgent> conn_iter(conns_); IntTcpAgent *curconn; if (seg_iter.count() == 0 && !slow_start_restart_) { return; } recover_ = sessionSeqno_ - 1; last_cwnd_action_ = CWND_ACTION_TIMEOUT; if (seg_iter.count() == 0 && restart_bugfix_) { slowdown(CLOSE_CWND_INIT); reset_rtx_timer(0,0); } else { slowdown(CLOSE_CWND_RESTART|CLOSE_SSTHRESH_HALF); reset_rtx_timer(0,1); } nrexmit_++; ownd_ = 0; owndCorrection_ = 0; while ((curconn = conn_iter()) != NULL) { curconn->t_seqno_ = curconn->highest_ack_ + 1; curconn->recover_ = curconn->maxseq_; curconn->last_cwnd_action_ = CWND_ACTION_TIMEOUT; } while ((curseg = seg_iter()) != NULL) { /* XXX exclude packets sent "recently"? */ curseg->size_ = 0; } send_much(NULL, 0, TCP_REASON_TIMEOUT); } else
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -