NewReno与Sack 仿真.docx
- 文档编号:10045080
- 上传时间:2023-05-23
- 格式:DOCX
- 页数:21
- 大小:77.54KB
NewReno与Sack 仿真.docx
《NewReno与Sack 仿真.docx》由会员分享,可在线阅读,更多相关《NewReno与Sack 仿真.docx(21页珍藏版)》请在冰点文库上搜索。
NewReno与Sack仿真
各种TCP版本之NewReno与Sack
实验目的
了解TCPNewReno与TCPSack的运行方式
基础知识回顾
在传送过程中,若同时有多个数据包在网络中遗失,大多数情况下TCPReno都必须等到超时(Timeout)时才能重送遗失的数据包。
主要原因在于:
TCPReno收到PartialACK就会结束快恢复(Fast-recovery),进入拥塞避免(CongestionAvoidance)阶段。
其中,PartialACK的ACK号码比先前收到的ACK大,但比稍早已送出的数据包编号小。
会出现PartialACK是因为使用快重传(Fast-Retransmit)重送遗失的数据包只更正了部分数据包遗失的错误,事实上,从接收端的观点看,仍有许多预期该收到的数据包未被收到。
TCPReno的传送端在重新收到CongestionAvoidance阶段时,由于没有足够的DuplicateACK可以触发重送的机制而只能等待超时。
超时对于TCP的效果有很大的影响。
首先,若遗失的数据包无法使用Fast-Retransmit/Fast-recovery重送,就必须等待超时来触发重送的机制,在等待超时的这段时间,TCP不能重送新的数据,这使得链路的使用率很低;其次,在超时之后,cwnd的值会被重设为1,也因此大大较低了TCP的传输效果。
【TCPNewReno】
NewReno是修改自Reno的TCP版本。
NewReno跟Reno在只有一个数据包遗失的情况下,其机制是一样的。
当同时有多个packet遗失时,NewReno就显示出了它的优势。
这个版本主要修改了TCPReno的Fast-recovery算法。
NewReno在收到PartialACK时,并不会立即结束Fast-recovery,相反,NewReno的传送端会持续地重送PartialACK之后的数据包,直到将所有遗失的数据包重送后才结束Fast-recovery。
这使得NewReno的传送端在网络有大量数据包遗失时不需等待Timeout就能更正此错误,减少大量数据包遗失对传输效果造成的影响。
NewReno大约每一个RTT时间可重送一个遗失的数据包,在Fast-recovery阶段,若允许的话,传送端会继续送出新的数据包,以增加链路的使用率。
【TCPwithSelectiveAcknowledgments(SACK)】
虽然NewReno可以解决大量数据包遗失的问题,但是NewReno在每个RTT时间只能一个数据包遗失的错误。
为了更有效地处理大量数据包遗失的问题,另一个解决方法就是让传送端知道哪些已经被接收端收到,但用此方法必须同时修改传送端和接收端的传送机制。
SACK是TCPReno的另一个衍生版本。
在这个版本中,加入了一个SACK选项(TCPoptionfield),允许接收端在返回DuplicateACK时,将已经收到的数据区段(连续收到的数据范围)返回给传送端,数据区段与数据区段之间的间隔就是接收端没有收到的数据。
传送端就知道哪些数据包是已经收到的,哪些是该重送的,因此SACK的传送端可以在一个RTT时间内重送一个以上的数据包。
NewReno,SACK与Reno之间的关系,可以用图1来表示:
实验步骤
在今天的实验中,我们来观察Reno,NewReno及SACK这3个TCP版本,并比较它们在遇到多数据包遗失时的异同。
l 仿真实验结果图(图2)
上图对于大家可能不太陌生。
我们在上一个试验(各种TCP版本之Tahoe与Reno)中已经描述并使用过,就不在赘述。
有一点区别在于:
Buffersize=15。
为什么呢?
因为NewReno和Sack主要解决大量数据包遗失问题,将r0与r1间的队列缓冲区设置得小一点,更容易遗失数据包,观察实验结果。
【实验1:
TCPReno】
² TCL程序代码(假设我将此代码保存于/home/ns下的tcpversion1.tcl中)
if{$argc!
=1}{
puts"Usage:
nstcpversion1.tclTCPversion"
puts"Example:
nstcpversion1.tclTahoeornstcpversion1.tclReno"
exit
}
setpar1[lindex$argv0]
#产生一个仿真的对象
setns[newSimulator]
#打开一个tracefile,用来记录数据包传送的过程
setnd[openout-$par1.trw]
$nstrace-all$nd
#打开一个文件用来记录cwnd变化情况
setf0[opencwnd-$par1.trw]
#定义一个结束的程序
procfinish{}{
globalnsndf0tcppar1
#显示最后的平均吞吐量,等于收到的ack数目(相当于发送成功的数据包数)*每个数据包的大小/传送时间(单位为:
b/s)
puts[format"averagethroughput:
%.1fKbps"\[expr[$tcpsetack_]*([$tcpsetpacketSize_])*8/1000.0/10]]
$nsflush-trace
#关闭文件
close$nd
close$f0
#使用awk分析记录文件,以观察队列的变化。
“exec”使得awk可以在tcl
#代码执行期间直接执行
#将out-$par1.tr文件用awk分析TCP各版本队列长度变化情况后获得的
#结果保存到queue_length-$par1.tr中
execawk{
BEGIN{
highest_packet_id=-1;
packet_count=0;
q_len=0;
}
{
#action,time,src_node,dst_node……packet_id等是trace文件对应项
action=$1;
time=$2;
src_node=$3;
dst_node=$4;
type=$5;
flow_id=$8;
seq_no=$11;
packet_id=$12;
#如果源节点为0,目的节点为1
if(src_node=="0"&&dst_node=="1"){
if(packet_id>highest_packet_id){
highest_packet_id=packet_id;
}
#假如是“入队”
if(action=="+"){
q_len++;
printtime,q_len;
}
#假如是“出队”或“丢包”
elseif(action=="-"||action=="d"){
q_len--;
printtime,q_len;
}
}
}
}out-$par1.tr>queue_length-$par1.tr
#将out-$par1.tr文件用awk分析TCP各版本数据包丢包情况后获得的结
#果保存到drop_no-$par1.tr中
execawk{
BEGIN{
drop_no=0;
}
{
action=$1;
time=$2;
src_node=$3;
dst_node=$4;
type=$5;
flow_id=$8;
seq_no=$11;
packet_id=$12;
#如果结点是r0与r1
if(src_node=="0"&&dst_node=="1"){
#如果行为时“丢包(drop)”
if(action=="d"){
drop_no++;
printdrop_no,time,flow_id,seq_no;
}
}
}
}out-$par1.tr>drop_no-$par1.tr
exit0
}
#定义一个记录的程序,每隔0.01s就去记录当时的cwnd,当然,这个间隔#时间0.01s完全可以改。
procrecord{}{
globalnstcpf0
setnow[$nsnow]
puts$f0"$now[$tcpsetcwnd_]"
$nsat[expr$now+0.01]"record"
}
#产生传送结点n0,路由器r1,r2和接收结点n1
setr0[$nsnode]
setr1[$nsnode]
setn0[$nsnode]
setn1[$nsnode]
#建立链接
$nsduplex-link$n0$r010Mb1msDropTail
$nsduplex-link$r0$r11Mb4msDropTail
$nsduplex-link$r1$n110Mb1msDropTail
#设置队列长度为15个数据包大小
setbuffer_size15
$nsqueue-limit$r0$r1$buffer_size
#根据用户的设置,指定TCP版本
if{$par1=="Reno"}{
settcp[newAgent/TCP/Reno]
settcpsink[newAgent/TCPSink]
$tcpsetdebug_0
}elseif{$par1=="Newreno"}{
settcp[newAgent/TCP/Newreno]
settcpsink[newAgent/TCPSink]
$tcpsetdebug_0
}else{
settcp[newAgent/TCP/Sack1]
settcpsink[newAgent/TCPSink/Sack1]
$tcpsetdebug_0
}
$nsattach-agent$n0$tcp
#将awnd的值设为24,这是advertisedwindow的上限
#advertisedwindow是接收端缓冲区可以容纳的数据包上限,
#因此当congestionwindow的值大于24时,TCP的传送端
#会执行流量控制,以避免传送得太快而导致接收端的缓冲区溢满
$tcpsetwindow_24
$nsattach-agent$n1$tcpsink
$nsconnect$tcp$tcpsink
#建立FTP应用程序
setftp[newApplication/FTP]
$ftpattach-agent$tcp
#在0.0s时,开始传送
$nsat0.0"$ftpstart"
#在10.0s时,结束传送
$nsat10.0"$ftpstop"
#在0.0s时,调用record来记录TCP的cwnd变化情况
$nsat0.0"record"
#在第10.0s时调用finish来结束模拟
$nsat10.0"finish"
#计算在传输路径上大约可以容纳多少个数据包
#计算方式:
在瓶颈链路上每秒可以传送的数据包数*RTT+队列缓冲区大小
puts[format"onpath:
%.2fpackets"\
[expr(1000000/(8*([$tcpsetpacketSize_]+40))*((1+4+1)*2*0.001))+$buffer_size]]
#执行模拟
$nsrun
² 执行方法
[root@localhostjdk1.6.0_18]#cd/home/ns
[root@localhostns]#nstcpversion1.tclReno
² 执行结果
onpath:
16.44packets
averagethroughput:
924.8Kbps
在这个例子中,我们将队列的大小设置为15个数据包。
通过计算,当路径上的数据包超过16.44个时,就会开始丢包。
现在传送端很容易会因为传送太快而产生多数据包遗失,这种情况在TCPTahoe/Reon中很容易导致Timeout发生。
² 打开drop_no_Reno.tr,查看丢包情况:
10.160008032
20.168328034
30.176648036
40.184968038
50.193288040
60.201608042
70.209928044
80.218248046
91.8698320196
103.0263120335
114.1744720473
125.3226320611
136.4791120750
147.6272720888
158.77543201026
169.93191201165
每行数据分4列,依次是:
drop_no,time,flow_id,seq_no(即丢包序号,丢包时间,数据流标号,数据包的序号)。
例如第一行表示在0.1600008s时,0号数据流丢掉了第一个数据包32。
² 使用gnuplot将cwnd的变化情形画出来。
(请务必首先进入/home/ns目录)
[root@localhostns]#gnuplot
gnuplot>settitle"Reno"
gnuplot>setxlabel"time"
gnuplot>setylabel"cwnd"
gnuplot>setterminalpng
Terminaltypesetto'png'
Optionsare'smallcolor'
gnuplot>setoutput"cwnd-Reno.gif"
gnuplot>plot"cwnd-Reno.tr"withlinespoints1
发现没有任何反应,但我们到/home/ns/目录下即可发现文件cwnd-Reno.gif,其图形如下(图3)所示:
图3cwnd的变化情况
(备注:
有些书上gnuplot>setterminalpng写的是gnuplot>setterminalgif,其实是不对的!
由于法律的原因,gnuplot4.0移除了对gif的支持,我用的版本也不支持此命令,而支持png格式。
但是,生成的图形主动会转化为jpg格式。
)
从图3中可观察到cwnd的变化情况:
大约在0.65s时,有一个Timeout
事件发生。
此外,为了观察r0与r1之间这条链路的使用情况,我们在TCL脚本的finish{}程序中加入了awk程序来帮助我们分析记录文件,以观察队列的变化。
² 使用gnuplot把队列长度画出来。
[root@localhostns]#gnuplot
gnuplot>settitle"Reno"
gnuplot>setxlabel"time"
gnuplot>setylabel"queuelength"
gnuplot>setterminalpng
Terminaltypesetto'png'
Optionsare'smallcolor'
gnuplot>setoutput"queue_length_Reno.gif"
gnuplot>plot"queue_length-Reno.tr"withlines1
我们在/home/ns/下即可发现文件queue_length_Reno.gif。
其图形如图4所示:
图4Reno的队列长度变化情况
大约0.5-0.7s期间(确切的说,在0.411368s-0.653736s),由于传送端没有再继续送出新的数据(等待超时),所以瓶颈(r0与r1间)的缓冲区都是空的。
【实验2:
观察TCPNewreno】
² TCL程序代码
TCL代码就是上述代码(tcpversion1.tcp)
² 执行方法
[root@localhostroot]#cd/home/ns
[root@localhostns]#nstcpversion1.tclNewreno
² 执行结果
onpath:
16.44packets
averagethroughput:
956.8Kbps
² 在/home/ns/中查找drop_no-Newreno.tr,查看Newreno的丢包情况:
10.160008032
20.168328034
30.176648036
40.184968038
50.193288040
60.201608042
70.209928044
80.218248046
91.2057360156
102.3538960294
113.5103760433
124.6585360571
135.8066960709
146.9631760848
158.1113360986
169.25949601124
² 同样,用gnuplot将cwnd变化情况画出来
[root@localhostns]#gnuplot
gnuplot>settitle"NewReno"
gnuplot>setxlabel"time"
gnuplot>setylabel"cwnd"
gnuplot>setterminalpng
Terminaltypesetto'png'
Optionsare'smallcolor'
gnuplot>setoutput"cwnd-NewReno.gif"
gnuplot>plot"cwnd-Newreno.tr"withlinespoints1
我们在/home/ns中即可发现cwnd-NewReno.gif,其图形如图5所示:
图5TCPNewRenocwnd的变化情况
从执行结果可以看出,NewReno的平均吞吐量(averagethroughput)比Reno的平均吞吐量大一点,效果好一些!
从图5中可以看到,在t=0.6s左右,NewReno一下送出了许多数据包,这种急速送出数据包的行为有时候在网络拥塞时很容易造成丢包现象。
造成这种现象的原因是:
NewReno在结束FastRecovery时,由于一次ACK回来的数据包较多,再加上传送端的SequenceNumber已经在重送过程中后移,所以有可能造成传送端在重新进入CongestionAvoidance阶段时,马上送出很多数据包。
若想消除这种急速送出数据包的现象,可使用TCP的“maxburst”参数限制每次收到ACK最多能送出的数据包数。
例如:
$tcpsetmaxburst_2
限制每次收到ACK最多只能送出2个数据包。
² 随后,用gnuplot把NewReno的队列长度画出来:
[root@localhostns]#gnuplot
gnuplot>settitle"Newreno"
gnuplot>setxlabel"time"
gnuplot>setylabel"queuelength"
gnuplot>setterminalpng
Terminaltypesetto'png'
Optionsare'smallcolor'
gnuplot>setoutput"queue_length-Newreno.gif"
gnuplot>plot"queue_length-Newreno.tr"withlines1
在/home/ns/下即可看见文件queue_length-Newreno.gif,如下图(图6)所示:
图6Newreno的队列长度变化情况
通过图6,我们发现在0.5s-0.7s之间,瓶颈的缓冲区并非为空。
【实验3:
SACK】
² TCL程序代码
TCL代码就是上述代码(tcpversion1.tcp)
² 执行方法
在NS2中已经有内建的SACK模块可以使用,使用时只需调用“TCP/Sack1”
这个Agent即可。
由于SACK修改了TCP的接收端,因此接收端的部分要使用别的TCPSink,目前可以使用的TCPSink有“TCPSink/Sack1”及“TCPSink/Sack1/DelAck”两种,其中,Sack1/DelAck有支持DelayACK的功能。
[root@localhostroot]#cd/home/ns
[root@localhostns]#nstcpversion1.tclSack
² 执行结果
onpath:
16.44packets
averagethroughput:
958.4Kbps
² 在/home/ns/目录下查找drop_no-Sack.tr,可见Sack的丢包情况为:
10.160008032
20.168328034
30.176648036
40.184968038
50.193288040
60.201608042
70.209928044
80.218248046
91.1001680145
102.2566480284
113.4214480424
124.5779280563
135.7344080702
146.8992080842
158.0556880981
169.21216801120
² 使用gnuplot将cwnd变化情形画出来。
[root@localhostns]#gnuplot
gnuplot>settitle"Sack"
gnuplot>setxlabel"time"
gnuplot>setylabel"cwnd"
gnuplot>setterminalpng
Terminaltypesetto'png'
Optionsare'smallcolor'
gnuplot>setoutput"cwnd-Sack.gif"
gnuplot>plot"cwnd-Sack.tr"withlinespoints1
我们在/home/ns中即可看见文件cwnd-Sack.gif,打开,如下图(图7)所示:
图7SACK的cwnd变化情况
通过SACK选项,传送端可以很明确地知道哪些数据包已经被接收端收到,并且直接针对部分遗失部分重送。
因此,可缩短错误回复(Error
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- NewReno与Sack 仿真 NewReno Sack