分享

NS2简单又经典的入门教程

 刀首木 2018-09-11

实验内容:awk和gnuplot对ns模拟之后.tr文件的处理实验

1、实验用网络拓扑图为

    这个网络的环境包含了四个网络节点(n0,n1,n2,n3)如下图所示。网络节点n0到节点n2之间,和节点n1到节点n2之间的网络频宽(bandwidth)是2Mbps,延迟時间(propagation delay)是10ms。网络拓朴中的频宽瓶颈是在节点n2到节点n3之间,频宽为1.7Mbps,延迟的時间为20ms。每个网络节都是采用DropTail queue的方式,且在节点n2到节点n3之间的最大队列长度是10个封包的长度。在节点n0到n3之间会有一条FTP的连线,FTP应用程式是架架在TCP之上,所以在写模拟环境的描述语言的時候,必需先建立一条TCP的连线,在來源端n0上使用TCP agent产生”tcp”來发送TCP的封包;在目的地端n3使用TCPsink agent产生”sink”來接受TCP的资料、並产生回覆封包(ACK)回传送端、最后把接收的TCP封包释放。最后要把这两个agent连起來(connect),连线才能建立。若是沒有額外的參数设定,TCP封包的长度为1Kbytes。在这里顺便补充說明一下,对于ns2模拟參数內定值设定是在ns-allinone-2.27\ns-2.27\tcl\lib目錄下的ns-default.tcl,有想要进一步了解的人,可以去查看此档。另外,在节点n1到n3之间有一条固定的传输速率的连线(Constant Bit Rate,CBR),CBR应用程式是架架在UDP之上,因此必需在n1使用UDP agent來产生”udp”用來发送UDP封包,在n3上使用Null agent來产生”sink”以接收由n1传送过來的UDP封包,然后把接收的封包释放。CBR的传送速度为1Mbps,每一个封包大小为1Kbytes。CBR是在0.1秒开始传送,在4.5秒結束传输;FTP是在1.0秒开始传送,4.0秒結束传输。

2、程序源代码
编辑一个四个结点的网络源文件,保存名为tool.tcl
# 产生一个模拟的物件
set ns [new Simulator]
#針对不同的资料流定义不同的顏色,这是要给NAM用的

$ns color 1 Blue
$ns color 2 Red

#开启一个NAM trace file
set nf [open out.nam w]
$ns namtrace-all $nf

#开启一个trace file,用來记录封包传送的过程
set nd [open out.tr w]
$ns trace-all $nd
#定义一个結束的程序
proc finish {} {
        global ns nf nd
        $ns flush-trace
        close $nf
        close $nd 
        #以背景执行的方式去执行NAM
        exec nam out.nam &
        exit 0
}

#产生四个网络节点
set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]
set n3 [$ns node]

#把节点连接起來
$ns duplex-link $n0 $n2 2Mb 10ms DropTail
$ns duplex-link $n1 $n2 2Mb 10ms DropTail
$ns duplex-link $n2 $n3 1.7Mb 20ms DropTail

#设定ns2到n3之间的Queue Size为10个封包大小
$ns queue-limit $n2 $n3 10
#设定节点的位置,这是要给NAM用的
$ns duplex-link-op $n0 $n2 orient right-down
$ns duplex-link-op $n1 $n2 orient right-up
$ns duplex-link-op $n2 $n3 orient right

#观测n2到n3之间queue的变化,这是要给NAM用的
$ns duplex-link-op $n2 $n3 queuePos 0.5

#建立一条TCP的连线
set tcp [new Agent/TCP]
$tcp set class_ 2
$ns attach-agent $n0 $tcp
set sink [new Agent/TCPSink]
$ns attach-agent $n3 $sink
$ns connect $tcp $sink

#在NAM中,TCP的连线会以蓝色表示
$tcp set fid_ 1
#在TCP连线之上建立FTP应用程式
set ftp [new Application/FTP]
$ftp attach-agent $tcp
$ftp set type_ FTP

#建立一条UDP的连线
set udp [new Agent/UDP]
$ns attach-agent $n1 $udp
set null [new Agent/Null]
$ns attach-agent $n3 $null
$ns connect $udp $null

#在NAM中,UDP的连线会以紅色表示
$udp set fid_ 2

#在UDP连线之上建立CBR应用程式
set cbr [new Application/Traffic/CBR]
$cbr attach-agent $udp
$cbr set type_ CBR
$cbr set packet_size_ 1000
$cbr set rate_ 1mb
$cbr set random_ false

#设定FTP和CBR资料传送开始和結束時间
$ns at 0.1 "$cbr start"
$ns at 1.0 "$ftp start"
$ns at 4.0 "$ftp stop"
$ns at 4.5 "$cbr stop"

#結束TCP的连线(不一定需要写下面的程式來实际結束连线)
$ns at 4.5 "$ns detach-agent $n0 $tcp ; $ns detach-agent $n3 $sink"
#在模拟环境中,5秒后去呼叫finish來結束模拟(这样要注意模拟环境中
#的5秒並不一定等于实际模拟的時间

$ns at 5.0 "finish"

#执行模拟
$ns run

3、运行ns tool.tcl得到下图
 

4、对trafic trace文件的分析
运行ns之后,得到out.tr和out.nam文件,我们重点分析.tr文件。
局部trace数据
+ 0.1 1 2 cbr 1000 ------- 2 1.0 3.1 0 0
- 0.1 1 2 cbr 1000 ------- 2 1.0 3.1 0 0
+ 0.108 1 2 cbr 1000 ------- 2 1.0 3.1 1 1
- 0.108 1 2 cbr 1000 ------- 2 1.0 3.1 1 1
r 0.114 1 2 cbr 1000 ------- 2 1.0 3.1 0 0
+ 0.114 2 3 cbr 1000 ------- 2 1.0 3.1 0 0
- 0.114 2 3 cbr 1000 ------- 2 1.0 3.1 0 0
+ 0.116 1 2 cbr 1000 ------- 2 1.0 3.1 2 2
- 0.116 1 2 cbr 1000 ------- 2 1.0 3.1 2 2
r 0.122 1 2 cbr 1000 ------- 2 1.0 3.1 1 1
+ 0.122 2 3 cbr 1000 ------- 2 1.0 3.1 1 1
- 0.122 2 3 cbr 1000 ------- 2 1.0 3.1 1 1
+ 0.124 1 2 cbr 1000 ------- 2 1.0 3.1 3 3
- 0.124 1 2 cbr 1000 ------- 2 1.0 3.1 3 3
r 0.13 1 2 cbr 1000 ------- 2 1.0 3.1 2 2
+ 0.13 2 3 cbr 1000 ------- 2 1.0 3.1 2 2
- 0.13 2 3 cbr 1000 ------- 2 1.0 3.1 2 2
+ 0.132 1 2 cbr 1000 ------- 2 1.0 3.1 4 4

每一笔记录的开始都是封包事件发生的原因,若是r则表示封包被某个节点所接收,若是+则表示进入了队列,若是-则表示离开队列,若是d则表示封包被队列所丟棄。接著的第二个栏位表示的是事件发生的時间;栏位三和栏位四表示事件发生的地点(從from node到to node);栏位五表示封包的形态;栏位六是封包的大小,栏位七是封包的旗标标註;栏位八表示封包是属于那一个资料流;栏位九和栏位十是表示封包的來源端和目的端,这两个栏位的格式是a.b,a代表节点編号,b表示端口号(port number);栏位十一表示封包的序号;最后栏位十二表示封包的id。以前面trace file的第一笔为例,意思就是說有一个封包pakcet id为0,资料流id为2,序号为0,长度为1000 bytes,形态为CBR,它是從來源端1.0要到目的地3.1,在時间0.1秒的時候,從节点1进入了节点2的队列中。

4、如何用awk分析tarace file,以得到Throughput、Delay、Jitter、和Loss Rate

awk的工作流程
工作流程: 执行awk時, 它会反複进行下列四步驟。
1. 自動從指定的资料档中读取一笔资料列。
2. 自動更新(Update)相關的內建变数之值。
3. 逐次执行程式中 所有 的 Pattern { Actions } 指令。
4. 当执行完程式中所有 Pattern { Actions }時,若资料档中还有未读取的料,则反覆执行步驟1到步驟4。
awk会自動重覆进行上述的四个步驟,所以使用者不須在程式中写这个迴圈。

[End-to-End Delay]
笔者把量测CBR封包端点到端点间延迟時间的awk程式,写在档案measure-delay.awk档案中,读者可以參考此范例,修改成符合读者需求的程式。
BEGIN {
#程式初始化,设定一变数以记录目前最高处理封包的ID。
     highest_packet_id = 0;
}
{
   action = $1;
   time = $2;
   node_1 = $3;
   node_2 = $4;
   type = $5;
   flow_id = $8; 
   node_1_address = $9;
   node_2_address = $10; 
   seq_no = $11;
   packet_id = $12;
#记录目前最高的packet ID
   if ( packet_id > highest_packet_id )
        highest_packet_id = packet_id;

#记录封包的传送時间
   if ( start_time[packet_id] == 0 )  
       start_time[packet_id] = time;

#记录CBR (flow_id=2) 的接收時间
   if ( flow_id == 2 && action != "d" ) {
      if ( action == "r" ) {
         end_time[packet_id] = time;
      }
   } else {
#把不是flow_id=2的封包或者是flow_id=2但此封包被drop的時间设为-1
      end_time[packet_id] = -1;
   }
}                                                

END {
#当资料列全部读取完后,开始计算有效封包的端点到端点延迟時间 
    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 ) printf("%f %f\n", start, packet_duration);
   }
}

执行方法: ($为shell的提示符号)
$awk -f measure-delay.awk out.tr

若是要把結果存到档案,可使用导向的方式。(把結果存到cbr_delay档案中)
$awk -f measure-delay.awk out.tr > cbr_delay
得到的结果是:
0.100000 0.038706
0.108000 0.038706
0.116000 0.038706
0.124000 0.038706
0.132000 0.038706
0.140000 0.038706
0.148000 0.038706
0.156000 0.038706
0.164000 0.038706
0.172000 0.038706
0.180000 0.038706
0.188000 0.038706
0.196000 0.038706
0.204000 0.038706
0.212000 0.038706
0.220000 0.038706
0.228000 0.038706
0.236000 0.038706

[Jitter]

延迟变量。Jitter越大,则表示网络越不穩定。笔者把量测CBR flow的Jitter的awk写在档案measure-jitter.awk內。

BEGIN {
#程式初始化
   old_time=0;
   old_seq_no=0;
   i=0;
}

{
   action = $1;
   time = $2;
   node_1 = $3;
   node_2 = $4;
   type = $5;
   flow_id = $8;
   node_1_address = $9;
   node_2_address = $10;
   seq_no = $11;
   packet_id = $12;

#判断是否为n2传送到n3,且封包形态为cbr,動作为接受封包
   if(node_1==2 && node_2==3 && type=="cbr" && action=="r") {

#求出目前封包的序号和上次成功接收的序号差值
       dif=seq_no-old_seq_no;

#处理第一个接收封包
        if(dif==0)  
          dif=1;
#求出jitter
          jitter=(time-old_time)/dif;
          seq=seq_no;
              i=i+1;
          old_seq_no=seq_no;
          old_time=time;
   }     
}

END {
   for (j=1; j <i ;j++)
    printf("%d\t%f\n",seq[j],jitter[j]);
}

运行
$awk -f measure-jitter.awk out.tr > cbr_jitter

cbr_jitter结果为

1     0.008000
2     0.008000
3     0.008000
4     0.008000
5     0.008000
6     0.008000
7     0.008000
8     0.008000
9     0.008000

[Loss]

笔者把量测CBR Packet Loss的情況写在档案measure-drop.awk內。
BEGIN {
#程式初始化,设定一变数记录packet被drop的数目
       fsDrops = 0;
       numFs = 0;
}

{
   action = $1;
   time = $2;
   node_1 = $3;
   node_2 = $4;
   src = $5;
   flow_id = $8;
   node_1_address = $9;
   node_2_address = $10;
   seq_no = $11;
   packet_id = $12;

#统计從n1送出多少packets
       if (node_1==1 && node_2==2 && action == "+") 
              numFs++;

#统计flow_id为2,且被drop的封包
       if (flow_id==2 && action == "d") 
              fsDrops++;
}
END {
       printf("number of packets sent:%d lost:%d\n", numFs, fsDrops);
}

执行方法: ($为shell的提示符号)
$awk -f measure-drop.awk out.tr >cbr_lose
运行得到的结果是:
number of packets sent:550 lost:8

[Throughput]
笔者把量测CBR Throughput的情況写在档案measure-throughput.awk內。在这里的Throughput是指average throughput。
BEGIN {
       init=0;
       i=0;
}

{
     action = $1;
     time = $2;
     node_1 = $3;
     node_2 = $4;
     src = $5;
     pktsize = $6;
     flow_id = $8;
     node_1_address = $9;
     node_2_address = $10;
     seq_no = $11;
     packet_id = $12;

      if(action=="r" && node_1==2 && node_2==3 && flow_id==2) {
             pkt_byte_sum[i+1]=pkt_byte_sum+ pktsize;
              if(init==0) {
                     start_time = time;
                     init = 1;
              }
      
              end_time = time;
              i = i+1;
       }
}

END {
#为了画图好看,把第一笔记录的throughput设为零,以表示传输开始
       printf("%.2f\t%.2f\n", end_time[0], 0); 
       for(j=1 ; j<i ; j++){
              th = pkt_byte_sum[j] / (end_time[j] - start_time)*8/1000;
              printf("%.2f\t%.2f\n", end_time[j], th);
       }
#为了画图好看,把第后一笔记录的throughput再设为零,以表示传输結束
       printf("%.2f\t%.2f\n", end_time[i-1], 0);
}
运行
$awk -f measure-throughput.awk out.tr > cbr_throughput

结果为:
0.14 0.00
0.15 1000.00
0.15 1000.00
0.16 1000.00
0.17 1000.00
0.18 1000.00
0.19 1000.00
0.19 1000.00
0.20 1000.00
0.21 1000.00
0.22 1000.00

紹完了如何量测End-to-End Delay、Jitter、Packet Loss、和Throughput后,最后就是要把量测的数据画出來。这里主要介绍gnuplot工具。

5、gnuplot
运行gnuplot进入gnuplot编辑模式
输入gnuplot> plot “cbr_delay”
得到结果
修改环境参数:
(1)       坐标轴(Axis)
 
标点设定
 xtics,ytics
 
网格设定
 grid
 
坐标显示方式
 logscale
 
显示范围设定
 autoscale,xrange,yrange 
 
坐标轴显示与否
 xzeroaxis,yzeroaxis  
 

1)xtics是对 X 坐标轴上的标点做设定。如起始点、結束点、间隔或在轴上特定点放特定的名称。其语法为:

set xtics { {<start>, <incr>{, <end>}} |
              {({"<label>"} <pos> {, {"<label>"} <pos>}...)} }

unset xtics   # 不标示任何 X 轴上的标点。
show xtics   # 显示 X 轴标点的狀況。

例子:
画一个标准的sin(x)函数
gnuplot sin(x)

进行设定
set xtics -10,1,10
plot sin(x)


(2)       网格设定:在XY坐标平面上依刻度画上方格子。

gnuplot>set grid
gnuplot> plot sin(x)
运行后得到的结果:

若要把网格拿掉,只要再unset grid就可以。

(3)       坐标显示方式:

坐标显示方式 : 分为线性与对数两种。 一般为前者,若要改为对数方式,其语法为:

set logscale <axes> <base>

其中 axes 为 X 轴、Y 轴、Z 轴的任意組合。base 預设为 10。

(4)       显示范围设定:修改各轴的显示范围。Autoscale参数设定后自动调整显示范围。而xrange、yrange则是可以由使用者设定该轴的范围。以xrange为例,其语法为:

 set xrange [{<xmin> : <xmax>}]

其中參数 <xmin> 与 <xmax> 代表 X 轴的起点与終点,可以是数字或数學式子。

例:

gnuplot> set xrange [1:10]

gnuplot> plot sin(x)

 

(5)坐标轴显示与否设定 : 设定是否要画出坐标轴,以 X 轴为例:

set xzeroaxis       # 设定显示 X 坐标轴

unset xzeroaxis     # 设定不显示 X 坐标轴

show xzeroaxis     # 檢查 X 坐标轴显示与否

 

gnuplot> set  xzeroaxis

gnuplot> plot sin(x)

 

注意到图像中间的虚线就是x坐标轴。

1)标示(Label):GNUPLOT 除了绘出图形外,尚可加入注解做为辅助说明。这注解包括文字与线条两方面,其提供的设定有

            

功能
 绘图參数名称
 
线条
 arrow
 
文字注解
 key,label,title,xlabel,ylabel
 

说明:

a.线条:在图上画一线段 可以选择有无箭头。其语法为

set arrow {<tag>} {from <sx>,<sy>{,<sz>}}

                 {to <ex>,<ey>{,<ez>}} {{no}head}

unset arrow {<tag>}      # 刪除一线条

show arrow             # 显示线条使用情況

其中參数 <tag> 是给該条线条一个整数名称,若不设定则为最小可用整数。此线条由坐标(sx, sy, sz)到(ex, ey, ez)(在2D中为 (sx, sy)到(ex, ey))。參数 nohead 为画沒有箭头的线段,參数 head 或沒有 nohead 为画有箭头的线段。

#画一帶有箭头的线条由原点到 (1,2)。

gnuplot> set arrow to 1,2

画一名为3的帶箭头线条由(0.4, 0.3 ) 到 (0.2, 0.1)。

gnuplot> set arrow 3 from 0.4, 0.3 to 0.2, 0.1

 

       #刪除名为3的线条。

       gnuplot>unset arrow 3

 

       #刪除所有线条。

       guplot> unset arrow

b.文字注释:

分为设定分为设定标头(title)和标示(label)

标头(title):设定为在图的正上方加上說明本图的文字。其语法为:

       set title {"<title-text>"} {<xoff>}{,<yoff>}

show title

其中设定參数 <xoff> 或 <yoff> 为微调标头放置的位置。 xlabel, ylabel的语法与title相同,其各自描述一坐标轴。

 

标示 (label):为在图上任一位置加上文字說明,一般与线条一併使用。

       set label {<tag>} {"<label_text>"}

           {at <x>,<y>{,<z>}}{<justification>}

       unset label {<tag>}          # 刪除一标示

show label                # 显示标示使用情況

其中參数<tag>与"线条" (arrow) 中<tag>意义相同,用以区別不同的 label。參数 <justification> 是调整文字放置的位置,可以是 left,right 或 center。

       # 将 y=x 放在坐标 (1,2) 之处。

gnuplot> set label “y=x”at 1,2

 

       # 将 y=x^2 放在坐标 (2,3) 之处,并且命名为 3。

       gnuplot> set label 3 "y=x^2" at 2,3 right

 

       # 将名为 3 的标示居中放置。

     gnuplot> set label 3 center

 

# 刪除名为3的标示。

gnuplot> unset label 3

 

# 刪除所有标示。

gnuplot> unsel label

 

一般绘一图形后,gnuplot会将函数名称或图形档案名称置于右上角。 key參数设定可改變名称放置位置。其语法为:

       set key

       set key <x>,<y>{,<z>}  #其中參数 <x>, <y>, <z> 设定名称放置位置。

       unset key        #不显示名称

       show key              #再度显示名称

[例]

gnuplot> set title “cbr_delay”

gnuplot> set xlabel “simulation time”

gnuplot> set ylabel “delay time”

       gnuplot> unset key

       gnuplot> set label “constant delay= 0.038706 sec”at 0.1, 0.05

       gnuplot> set arrow from 0.5, 0.05 to 0.5, 0.04

 

2)图样(Style):gnuplot描绘数据资料图形是以读入档案中的坐标值后,以图样绘上。而描绘函数图形是计算若干点的函数值后,以某种图样将函数值绘上。一般是取样 100 点及采取线条作为图样。GNUPLOT 可提供 9 种图样,分別是

lines : 将相邻的点以线条连接。如 plot sin(x) with lines。

points : 将每一点以一符号绘上。如 plot sin(x) with points

linespoints : 同時具有 lines 及 points 的功能。如 plot sin(x) with linespoints。

impulses : 将每一点画一垂直线至 X 轴。如 plot sin(x) with impulses。

dots : 将每一点绘一細点。如 plot sin(x) with dots。

steps : 以垂直线及水平线各一条來连接两点,形成梯形。如连接 (x1,y1),(x2,y2)两点,以(x1,y1)到(x2,y1)和(x2,y1)到(x2,y2) 两线段连接。如 plot sin(x) with steps。

errorbars : 对每一点坐标值 (x,y),画一由 (x,ylow) 至 (x,yhigh) 的线段。並在线段两端做上 tic mark。如plot sin(x) with errorbars。

boxes : The boxes style draws a box centred about the given x coordinate from the yaxis to the given y coordinate.如plot sin(x) with boxes。

boxerrorbars : 組合 errorbars 与 boxes 两者功能。如 plot sin(x) with boxerrorbars。

[例] 把cbr_delay中的数据用lines和points连起來。

       gnuplot> plot “cbr_delay” with linespoints

 

3)输出(Output):GNUPLOT 的输出參数设定有 terminal,output。不过在这里笔者只介紹如何把画出来的图存成Gif格式。

#把输出设成存成gif格式,內定为X11 terminal

gnuplot> set terminal gif

 

#把输出的档名设为cbr_delay.gif

gnuplot> set output “cbr_delay.gif”

 

#把资料重新绘一次

gnuplot> replot

 

注意:这个地方并没有生成想得到的gif文件。

尝试

set terminal pdf

set output “cbr_delay.pdf”

replot 也没有得到结果

 

总结:

这个实验主要掌握了一些基本的对数据处理的软件的使用方法,tcl运行后得到的.nam和.out文件需要用awk进行处理,处理的结果用gunplot画出来进行分析。

用awk对.tr处理文件可以用于四个方面的处理:

(1)End-to-End Delay

(2)Jitter

(3)Packet Loss

(4)Throughput

 

声明:实验的主要内容参考的是柯志亨博士的资料,如果需要更详细的了解柯志亨老师关于NS方面的研究成果,请关注http://140.116.72.80/~smallko/ns2/tool.htm
 

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多