队列管理机制
原文地址 :http://selab.whust.com/Display_Diary.aspx?DiaryID=47
?
實驗目的
? ?學習DropTail 和 RED 隊列管理機制,以了解主動式和被動式隊列管理的優缺點。
?背景知識
【DropTail 和被動式隊列管理機制】
?? 在Internet中最簡單也最普遍的隊列管理機制就是DropTail。當一個數據報到達隊列時,就把數據報放到隊列中等待被傳送,但由于隊列長度是有限的,因此如果數據流太大,而隊列沒有空間去暫存這些新到的數據報,就會把隊列最尾端的數據報丟棄,這樣的管理機制就叫做DropTail。很多時候,DropTail隊列管理機制會與FIFO(First In First Out)相結合,整個運作方式為:數據報傳送的順序與封包進入隊列的順序相同,先進入隊列的封包先傳送出去,后進入隊列的封包較晚傳送出去。如果隊列長度超過暫存空間的大小,就會把隊列最尾端的數據報丟棄。DropTail在丟棄數據報時,并不會去考慮要丟棄的數據報屬于哪個數據流,只是單純的把超過暫存空間大小的數據流丟棄,因此DropTail隊列管理機制的最大優點就是實際操作簡單。但是,有利有弊,正是由于這個特性,使得隊列在相當長的時間內處于充滿或幾乎充滿的狀態。而隊列管理機制最重要的目標之一是降低穩定狀態下隊列的長度,因為端點到端點的延遲主要由隊列中排隊等待造成的。
此外,DropTail容易造成TCP全局同步(TCP Global Synchronization)問題。由于Internet 上的數據流都具有突發性,到達路由器的封包也往往是突發的。如果此時隊列處于充滿或幾乎充滿狀態,就會導致在短時間內連續大量的丟包。而TCP數據流具有自適應特性(Adaptive),來源端發現封包丟失就會急速降低傳送速度,于是網絡擁塞情況得到緩解。但來源端在發現網絡不再擁塞后又開始增加發送速度,最終又造成網絡擁塞。這種現象就像一個循環,周而復始的進行下去,致使網絡長期處于鏈路利用率很低的狀態,降低了整體的吞吐量,這正是傳說中的“TCP全局同步”現象,這個現象,我們會在后面的實驗中通過網絡仿真產生的數據和圖形進行驗證。
除了DropTail外,另外兩種在隊列滿時用得比較多的隊列管理機制是Random Drop 和 Drop Front。當隊列滿時,前者從隊列中隨機找到一個數據報丟棄,讓新來的數據報進入隊列;后者從隊列前端把數據報丟棄,以便新來的數據報進入隊列。但這兩種隊列管理機制仍然存在“滿隊列”問題。由于這幾種方法都是在隊列滿時被迫丟包,因此被稱為被動式隊列管理。
?
【RED和主動式隊列管理機制】
與被動式隊列管理機制在隊列滿時被動丟包相比,主動式隊列管理機制在隊列未滿時就開始按一定概率丟棄數據報。這樣未雨綢繆,對具有擁塞控制的傳送端做流量速度管制,以避免滿隊列被迫丟包的兩種負面影響:端點到端點的延遲時間過長,鏈路利用率過低。而RED(Random Early Detection)就是一種典型的主動式隊列管理機制。
RED隊列管理機制使用平均隊列長度來預測即將發生的網絡擁塞,并采用隨機選擇的方式對數據報進行丟棄,使得擁塞發生前就會有擁塞控制的傳送端提示要進行流量速度管制,以避免擁塞發生。與此同時,由于RED是采用隨機的方式來丟棄封包,因此不同的TCP數據流對擁塞情況的反應不同步,因而解決了“TCP全局同步”現象。
簡言之,RED路由器由兩個獨立的算法組成:1.計算平均隊列長度(avg)的算法決定了路由器隊列容納突發性數據的程度;2.計算丟包概率(Pb)的算法決定了在當前擁塞程度下,路由器丟棄分組的概率。
RED計算平均隊列長度是采用加權平均方式,計算公式如下:
??? ????avg = (1- Wq)* avg + Wq * q
其中,avg是平均隊列長度,q是目前實際的隊列長度,Wq 為目前實際的隊列長度加權系數,其值在0與1之間。一般而言,設置得比較小,以便計算出來的平均隊列長度變化得比較慢,不會因為突發流量的到來而使平均隊列長度增加得過快,造成大量封包丟失。
決定要丟棄封包依據兩個閾值minth 和maxth ,當平均隊列長度avg 小于minth 時,所有的封包都允許進入隊列,但當avg超過maxth 時,所有的封包被直接丟棄,當avg介于minth 和maxth 時,則根據下面的概率公式來丟棄封包。
Pb ?= maxp * (avg - minth)/(maxth- minth)
其中的maxp為網管預先設置的丟棄概率值,Pb 為目前封包丟棄的計算值,其值變化如下圖所示:
?
?
??
?
而RED再真正決定是否要丟棄數據報,并不是采用Pb ,而是對Pb 進行如下修改,以作為實際封包丟棄概率:
?? ??Pa = Pb ?/ (1- count* Pb)
其中,count記錄了上一個封包丟棄后有多少數據報進入隊列。采用 Pa 是希望能讓數據報丟棄概率的分布更均勻。
可見,若想有效的使用RED,適當選擇Wq ?,minth ,? maxth ,maxp 等參數很關鍵。1993年 Floy S,Jacobson 發表了一篇題為“Random early detection gateways for congestion avoidance”的論文,將RED的算法,參數的設置,實驗的結果詳細的進行了分析和論證,大家可以在網上下載,進行參考。
?
實驗步驟
說了這么久,我們終于可以開始做實驗了!
1.????? 仿真的網絡結構圖
?????????????????????????????? ?
可能大家對這個結構圖已經不陌生了,r1和r2是路由器,其中的鏈路采用DropTail和RED隊列管理機制以作為效率分析的比較,頻率為56kbps,傳輸延遲為10ms。其中的數據流數目可由用戶在模擬時決定,下面的例子為10條TCP數據流。我們要比較的效率是這10條數據流的平均吞吐量、第一條數據流的端點到端點平均延遲時間和隊列長度變化。
2.????? TCL程序代碼 (假設我們將程序代碼保存于/home/ns下的queue.tcl中)
if {$argc !=2} {
?puts "Usage: ns queue.tcl queuetype_ noflows_"
?puts "Example: ns queue.tcl DropTail 10"
?puts "queuetype_: DropTail or RED"
?exit
?}
?
set par1 [lindex $argv 0]
set par2 [lindex $argv 1]
#產生一個仿真的對象
set ns [new Simulator]
#打開一個trace文件,用來記錄數據報傳送的過程
set nd [open out-$par1-$par2.tr w]
$ns trace-all $nd
#結束一個結束的程序
proc finish {} {
?global ns nd par2 tcp startT
?$ns flush-trace
?close $nd
?set time [$ns now]
?set sum_thgpt 0
# throughput = 收到ACK數 * Packet Size(Bit) / 傳送時間
# 收到Ack數 = 傳送出Packet 數
for {set i 0} {$i < $par2} {incr i 1} {
?set ackno_($i) [$tcp($i) set ack_ ]
?set thgpt($i) [expr $ackno_($i) *1000.0*8.0/($time-$startT($i))]
?#puts $thgpt($i)
?set sum_thgpt [expr $sum_thgpt+$thgpt($i)]
}
?
?set avgthgpt [expr $sum_thgpt/$par2]
?puts "average throughput: $avgthgpt (bps)"
?exit 0
}
#定義節點
for {set i 0} {$i<$par2} {incr i 1} {
?set src($i) [$ns node]
?set dst($i) [$ns node]
}
#產生兩個路由器
set r1 [$ns node]
set r2 [$ns node]
#把結點和路由器連接起來
for {set i 0} {$i<$par2} {incr i 1} {
? $ns duplex-link $src($i) $r1 100Mb [expr ($i*10)]ms DropTail
? $ns duplex-link $r2 $dst($i) 100Mb [expr ($i*10)]ms DropTail
?}
?
$ns duplex-link $r1 $r2 56k 10ms $par1
#設置r1和r2之間的Queue Size 為50個數據報大小
$ns queue-limit $r1 $r2 50
#記錄隊列長度
#Recording the length of queue
set q_ [[$ns link $r1 $r2] queue]
# set queuechan [open q-$par1-$par2.tr w]
# $q_ trace curq_
?
if {$par1=="RED"} {
#Using packet mode
$q_ set bytes_ false
$q_ set queue_in_bytes false
}
?
# $q_ attach $queuechan
?
for {set i 0} {$i<$par2} {incr i 1} {
?set tcp($i) [$ns create-connection TCP/Reno $src($i) TCPSink $dst($i) 0]
?$tcp($i) set fid_ $i
?}
#隨機在0與1之間決定數據流開始傳送的時間
set rng [new RNG]
?$rng seed 1
?
?set RVstart [new RandomVariable/Uniform]
?$RVstart set min_ 0
?$RVstart set max_ 1
?$RVstart use-rng $rng
?
?for {set i 0} {$i<$par2} {incr i 1} {
? set startT($i) [expr [$RVstart value]]
? #puts "startT($i) $startt($i)sec"
?}
?
#在指定時間,開始傳送數據
for {set i 0} {$i<$par2} {incr i 1} {
?set ftp($i) [$tcp($i) attach-app FTP]
?$ns at $startT($i) "$ftp($i) start"
}
?
#在第50s時區調用finish來結束模擬
$ns at 50.0 "finish"
$ns run
?
3.????? 執行方法和執行結果
(1)10條TCP數據流,采用DropTail 隊列管理機制:
[root@localhost ns]# ns queue.tcl DropTail 10
average throughput: 4353.6337788880564 (bps)
?
(2)10條TCP數據流,采用RED隊列管理機制:
?[root@localhost ns]# ns queue.tcl RED 10
average throughput: 4789.3897693204663 (bps)
結果分析:從上面的數據可知,在只有10條TCP數據流的情況下,RED隊列管理機制得到的吞吐量高于DropTail隊列管理機制。
知識拓展:上面是10條TCP數據流,我們還可以將數據流的數目改為15,20,25,30等,然后觀察平均吞吐量(average throughput)
?
4.????? 端點到端點平均延遲的awk程序 (假設我們將此awk程序保存于/home/ns下的measure-delay1.awk中)
#這是測量第一條TCP數據流數據報端點到端點間平均延遲時間的awk程序
#我們可以根據這個程序,舉一反三,寫出測量第2條以至第n條TCP/UDP
#數據流的awk程序
?
BEGIN {
?#程序初始化,設置一變量以記錄目前最高處理數據報的ID
?highest_packet_id = 0;
}
?
{
?#與trace文件結構對應
?action = $1;
?time = $2;
?from = $3;
?to = $4;
?type = $5;
?pktsize = $6;
?flow_id = $8;
?src = $9;
?dst = $10;
?seq_no = $11;
?packet_id = $12;
#記錄目前最高的packet ID
if( packet_id > highest_packet_id )
?highest_packet_id = packet_id;
#記錄第一條TCP(flow-id=0)的接收時間
if ( start_time[packet_id] == 0 )
?start_time[packet_id] = time;
?
#記錄第一條TCP(flow-id=0)的接收時間
if( flow_id==0 && action!="d" && type=="tcp" ) {
?? if ( action == "r" ) {
????? end_time[packet_id] = time;
????? }
? } else {
?#把不是flow-id=0 的封包或則flow-id=0 ,但此封包被drop的時間設置為-1
?? end_time[packet_id] = -1;
? }
}
?
END {
sum_delay=0;
no_sum=0;
#把數據全部讀取完后,開始計算有效數據報的端點到端點延遲時間
for( packet_id = 0; packet_id <= highest_packet_id; packet_id++ ) {
start = start_time[packet_id];
end = end_time[packet_id];
packet_duration = end-start;
?
#只把接收時間大于傳送時間的記錄列出來
if( start < end ) {
?#print ("%f %f/n",start,packet_duration);
?sum_delay+=packet_duration;
?no_sum+=1;
? }
?}
#求出數據報端點到端點的平均延遲時間
printf( "average delay: %f sec/n",sum_delay/no_sum );
}
?
5. 執行方法和執行結果:
(1)10條TCP數據流,采用DropTail隊列管理機制
? [root@localhost ns]# awk -f measure-delay1.awk out-DropTail-10.tr
average delay: 4.379053 sec
?? (2)10條TCP數據流,采用RED隊列管理機制
??? [root@localhost ns]# awk -f measure-delay1.awk out-RED-10.tr
average delay: 1.237935 sec
結果分析:從上面的數據可知,在只有10條TCP數據流的情況下,RED隊列管理機制得到的端點到端點的平均延遲時間低于DropTail隊列管理機制。
6. 使用gnuplot 觀察DropTail 和RED 隊列長度變化(假設我們要分析的q-DropTail-10.tr 和q-RED-10.tr文件都保存在/home/ns中)
? [root@localhost root]# cd /home/ns
[root@localhost ns]# gnuplot
?
??????? G N U P L O T
??????? Version 3.7 patchlevel 3
??????? last modified Thu Dec 12 13:00:00 GMT 2002
??????? System: Linux 2.4.20-8
?
??????? Copyright(C) 1986 - 1993, 1998 - 2002
??????? Thomas Williams, Colin Kelley and many others
?
??????? Type `help` to access the on-line reference manual
??????? The gnuplot FAQ is available from
??????? http://www.gnuplot.info/gnuplot-faq.html
?
??????? Send comments and requests for help to
??????? Send bugs, suggestions and mods to
?
?
Terminal type set to 'x11'
gnuplot> plot "q-RED-10.tr" using 2:3 with linespoints 1
顯示圖形如下:
???????
?
按照同樣的方法進入gnuplot,然后輸入:
gnuplot> plot "q-DropTail-10.tr" using 2:3 with linespoints 2
???????????????????????????????????????????????????????????? ^
得到的結果為:? x range is invalid
為什么呢?
我們從/home/ns中打開文件q-DropTail-10.tr,查看,發現此文件是空的。
原因何在呢?
我們來看queue.tcl中的這段代碼:
#記錄隊列長度
#Recording the length of queue
set q_ [[$ns link $r1 $r2] queue]
# set queuechan [open q-$par1-$par2.tr w]
# $q_ trace curq_
?
if {$par1=="RED"} {
#Using packet mode
$q_ set bytes_ false
$q_ set queue_in_bytes false
}
?
# $q_ attach $queuechan
?我們把記錄隊列長度的核心代碼set queuechan [open q-$par1-$par2.tr w] 、$q_ trace curq_ 、$q_ attach $queuechan 給注釋了!之所以這樣做,是因為NS2中并沒有提供追蹤DropTail隊列長度的功能。因此,現在的關鍵在于,如何在NS2中添加追蹤DropTail隊列長度的新協議。
?????? 這個問題還待研究。。。。。。
總結
- 上一篇: NS安装问题收集(3)
- 下一篇: set class_ x set fid