队列管理机制

    技术2022-05-20  50

    原文地址 :http://selab.whust.com/Display_Diary.aspx?DiaryID=47

     

    实验目的

       学习DropTail RED 队列管理机制,以了解主动式和被动式队列管理的优缺点。

     背景知识

    DropTail 和被动式队列管理机制】

       Internet中最简单也最普遍的队列管理机制就是DropTail。当一个数据报到达队列时,就把数据报放到队列中等待被传送,但由于队列长度是有限的,因此如果数据流太大,而队列没有空间去暂存这些新到的数据报,就会把队列最尾端的数据报丢弃,这样的管理机制就叫做DropTail。很多时候,DropTail队列管理机制会与FIFOFirst In First Out)相结合,整个运作方式为:数据报传送的顺序与封包进入队列的顺序相同,先进入队列的封包先传送出去,后进入队列的封包较晚传送出去。如果队列长度超过暂存空间的大小,就会把队列最尾端的数据报丢弃。DropTail在丢弃数据报时,并不会去考虑要丢弃的数据报属于哪个数据流,只是单纯的把超过暂存空间大小的数据流丢弃,因此DropTail队列管理机制的最大优点就是实际操作简单。但是,有利有弊,正是由于这个特性,使得队列在相当长的时间内处于充满或几乎充满的状态。而队列管理机制最重要的目标之一是降低稳定状态下队列的长度,因为端点到端点的延迟主要由队列中排队等待造成的。

    此外,DropTail容易造成TCP全局同步(TCP Global Synchronization)问题。由于Internet 上的数据流都具有突发性,到达路由器的封包也往往是突发的。如果此时队列处于充满或几乎充满状态,就会导致在短时间内连续大量的丢包。而TCP数据流具有自适应特性(Adaptive),来源端发现封包丢失就会急速降低传送速度,于是网络拥塞情况得到缓解。但来源端在发现网络不再拥塞后又开始增加发送速度,最终又造成网络拥塞。这种现象就像一个循环,周而复始的进行下去,致使网络长期处于链路利用率很低的状态,降低了整体的吞吐量,这正是传说中的“TCP全局同步”现象,这个现象,我们会在后面的实验中通过网络仿真产生的数据和图形进行验证。

    除了DropTail外,另外两种在队列满时用得比较多的队列管理机制是Random Drop Drop Front。当队列满时,前者从队列中随机找到一个数据报丢弃,让新来的数据报进入队列;后者从队列前端把数据报丢弃,以便新来的数据报进入队列。但这两种队列管理机制仍然存在“满队列”问题。由于这几种方法都是在队列满时被迫丢包,因此被称为被动式队列管理。

     

    RED和主动式队列管理机制】

    与被动式队列管理机制在队列满时被动丢包相比,主动式队列管理机制在队列未满时就开始按一定概率丢弃数据报。这样未雨绸缪,对具有拥塞控制的传送端做流量速度管制,以避免满队列被迫丢包的两种负面影响:端点到端点的延迟时间过长,链路利用率过低。而REDRandom Early Detection)就是一种典型的主动式队列管理机制。

    RED队列管理机制使用平均队列长度来预测即将发生的网络拥塞,并采用随机选择的方式对数据报进行丢弃,使得拥塞发生前就会有拥塞控制的传送端提示要进行流量速度管制,以避免拥塞发生。与此同时,由于RED是采用随机的方式来丢弃封包,因此不同的TCP数据流对拥塞情况的反应不同步,因而解决了“TCP全局同步”现象。

    简言之,RED路由器由两个独立的算法组成:1.计算平均队列长度(avg)的算法决定了路由器队列容纳突发性数据的程度;2.计算丢包概率(Pb)的算法决定了在当前拥塞程度下,路由器丢弃分组的概率。

    RED计算平均队列长度是采用加权平均方式,计算公式如下:

            avg = (1- Wq)* avg + Wq * q

    其中,avg是平均队列长度,q是目前实际的队列长度,Wq 为目前实际的队列长度加权系数,其值在01之间。一般而言,设置得比较小,以便计算出来的平均队列长度变化得比较慢,不会因为突发流量的到来而使平均队列长度增加得过快,造成大量封包丢失。

    决定要丢弃封包依据两个阈值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 SJacobson 发表了一篇题为“Random early detection gateways for congestion avoidance”的论文,将RED的算法,参数的设置,实验的结果详细的进行了分析和论证,大家可以在网上下载,进行参考。

     

    实验步骤

    说了这么久,我们终于可以开始做实验了!

    1.      仿真的网络结构图

                                    

    可能大家对这个结构图已经不陌生了,r1r2是路由器,其中的链路采用DropTailRED队列管理机制以作为效率分析的比较,频率为56kbps,传输延迟为10ms。其中的数据流数目可由用户在模拟时决定,下面的例子为10TCP数据流。我们要比较的效率是这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

    #设置r1r2之间的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

     }

    #随机在01之间决定数据流开始传送的时间

    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.      执行方法和执行结果

    110TCP数据流,采用DropTail 队列管理机制:

    [root@localhost ns]# ns queue.tcl DropTail 10

    average throughput: 4353.6337788880564 (bps)

     

    210TCP数据流,采用RED队列管理机制:

     [root@localhost ns]# ns queue.tcl RED 10

    average throughput: 4789.3897693204663 (bps)

    结果分析:从上面的数据可知,在只有10TCP数据流的情况下,RED队列管理机制得到的吞吐量高于DropTail队列管理机制。

    知识拓展:上面是10TCP数据流,我们还可以将数据流的数目改为15,20,25,30等,然后观察平均吞吐量(average throughput

     

    4.      端点到端点平均延迟的awk程序 (假设我们将此awk程序保存于/home/ns下的measure-delay1.awk中)

    #这是测量第一条TCP数据流数据报端点到端点间平均延迟时间的awk程序

    #我们可以根据这个程序,举一反三,写出测量第2条以至第nTCP/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;

    #记录第一条TCPflow-id=0)的接收时间

    if ( start_time[packet_id] == 0 )

     start_time[packet_id] = time;

     

    #记录第一条TCPflow-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. 执行方法和执行结果:

    110TCP数据流,采用DropTail队列管理机制

      [root@localhost ns]# awk -f measure-delay1.awk out-DropTail-10.tr

    average delay: 4.379053 sec

       210TCP数据流,采用RED队列管理机制

        [root@localhost ns]# awk -f measure-delay1.awk out-RED-10.tr

    average delay: 1.237935 sec

    结果分析:从上面的数据可知,在只有10TCP数据流的情况下,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队列长度的新协议。

           这个问题还待研究。。。。。。


    最新回复(0)