'Network'에 해당되는 글 204건

  1. 2009.01.18 network components, ns by example
  2. 2009.01.18 NS by Example - Network Components
  3. 2009.01.18 802.11 MAC code in NS-2 (version 2.28)
  4. 2009.01.18 802.11 MAC code in NS-2 (version 2.28)
  5. 2009.01.18 NS2_Reno, cwnd, ip packet size의 11Mbps 무선랜, 100Mbps유선랜 ns2_upstream10/downstream10
  6. 2009.01.18 NS2_스크립트 up_down_stream2.sh_upstream10/downstream10
  7. 2009.01.18 NS2_awk-ack_rec_wire_upstream10/downstream10
  8. 2009.01.18 NS2_awk-ack_rec_wireless_upstream10/downstream10
  9. 2009.01.18 NS2_awk-ack_send_wire_upstream10/downstream10
  10. 2009.01.18 NS2_awk-ack_send_wireless_upstream10/downstream10

network components, ns by example

|
NS2 Simple Simulation Example

2.2 Simple Simulation Example


이 section은 간단한 NS simulation script를 보여주며, 각 line이 무엇을 하는지를 설명한다. 예제3 은 간단한 network 구성을 생성하는 OTcl script이며, 그림4.에 있는 시뮬레이션 scenario를 동작한다. 이 시뮬레이션을 동작하기 위해서 "ns-simple"를 다운받고, shell prompt에서 "ns ns-simple.tcl"을 입력하라.




Example 3. A Simple NS Simulation Script
#Create a simulator object

set ns [new Simulator]


#Define different colors for data flows (for NAM)

$ns color 1 Blue

$ns color 2 Red


#Open the NAM trace file

set nf [open out.nam w]

$ns namtrace-all $nf


#Define a 'finish' procedure

proc finish {} {

global ns nf

$ns flush-trace

#Close the NAM trace file

close $nf

#Execute NAM on the trace file

exec nam out.nam &

exit 0

}


#Create four nodes

set n0 [$ns node]

set n1 [$ns node]

set n2 [$ns node]

set n3 [$ns node]


#Create links between the nodes

$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


#Set Queue Size of link (n2-n3) to 10

$ns queue-limit $n2 $n3 10


#Give node position (for 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


#Monitor the queue for link (n2-n3). (for NAM)

$ns duplex-link-op $n2 $n3 queuePos 0.5



#Setup a TCP connection

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

$tcp set fid_ 1

#Setup a FTP over TCP connection

set ftp [new Application/FTP]

$ftp attach-agent $tcp

$ftp set type_ FTP



#Setup a UDP connection

set udp [new Agent/UDP]

$ns attach-agent $n1 $udp

set null [new Agent/Null]

$ns attach-agent $n3 $null

$ns connect $udp $null

$udp set fid_ 2


#Setup a CBR over UDP connection

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



#Schedule events for the CBR and FTP agents

$ns at 0.1 "$cbr start"

$ns at 1.0 "$ftp start"

$ns at 4.0 "$ftp stop"

$ns at 4.5 "$cbr stop"


#Detach tcp and sink agents (not really necessary)

$ns at 4.5 "$ns detach-agent $n0 $tcp ; $ns detach-agent $n3 $sink"


#Call the finish procedure after 5 seconds of simulation time

$ns at 5.0 "finish"


#Print CBR packet size and interval

puts "CBR packet size = [$cbr set packet_size_]"

puts "CBR interval = [$cbr set interval_]"


#Run the simulation

$ns run






다음은 위 script에 대한 설명이다. 일반적으로 NS script는 Simulator object instance를 만들어서 시작한다.




○ set ns[new Simulator]:

NS simulator object instance를 생성하며, 변수 ns로 그것을 할당한다.(italics은 이 section에서 변수와 값으로 사용된다.) 이 라인의 역할은 다음과 같다.

-. packet format를 초기화(여기서는 이것을 무시)

-. scheduler를 생성(default는 calendar scheduler임)

-. default address format를 선택(여기서는 이것을 무시)


이 "Simulator" object는 다음의 일을 하는 member 함수를 가진다.


-. node와 link같은 복합 object를 생성(desired later)

-. 생성된 network 구성 object를 연결(ex. attach-agent)

-. network 구성 parameter를 set(mostly for compound object)

-. agent 사이의 연결 생성(ex. "tcp"와 "sink"사이의 연결을 만든다)

-. NAM display option을 규정

-. Etc.


member 함수의 대부분은 simulation setup(Overview section에서 plumbing 함수와 관련된)과 scheduling을 위해서 있다. 그러나, 그들 중 대부분은 NAM display를 위해서 있다. "Simulator" object member 함수 구현은 "ns-2/tcl/lib/ns-lib.tcl" file내에 위치해 있다.




○ $ns color fid color:

flow id(fid)에 의해 규정된 flow에 대한 packet의 color를 set 하는 것. 이 "Simulator" object의 member 함수는 NAM display를 위한 것이다. 그리고 실제적인 시뮬레이션 상에 어떤 효과도 미치지 않는다.




○ $ns namtrace-all file-descriptor:

이 member 함수는 NAM input format에 있는 simulation trace를 기록하기 위한 시뮬레이터를 말한다. 그것은 또한 trace가 $ns flush-trace 명령에 의해 나중에 쓰여질 file name을 준다.




○ proc finish {}:

이 시뮬레이션 뒤에 $ns at 5.0 "finish" 명령에 의해 호출된다. 이 함수에서 post-simulation process가 규정된다.




○ set n0 [$ns node]:

member 함수 node는 node를 생성한다. NS에 있는 node는 address와 port classifier들로 만들어진 복합 object이다.(다음 section에서 기술된다) 사용자는 주소와 port classifier object를 분리하여 생성하고, 그들을 함께 연결함으로써 node를 생성할 수 있다. 그러나, 이 Simulator object의 member 함수는 job를 보다 쉽게 만든다. node가 생성되는 방법을 보기 위해 file "ns-2/tcl/libs/ns-lib.tcl" 과 "ns-2/tcl/ns-node.tcl"을 살펴보라.




○ $ns duplex-link node1 node2 bandwidth delay queue-type:

상술된 bandwidth와 delay의 두 개의 simplex link를 생성하며, 두 개의 상술된 node를 연결한다. NS에서 node의 출력 queue는 link의 부분으로 구현된다. 그러므로, user는 link를 생성할 때 queue type를 상술해야 한다. 위의 시뮬레이션 script에서, DropTail queue가 사용된다. 만일 독자가 RED queue를 사용하기를 원한다면, 간단하게 DropTail을 RED로 대치하면 된다. link의 NS 구현은 다음 section에서 보여진다. node처럼, link도 compound object이며 user는 그것의 sub-object를 생성하고 그들과 node를 연결할 수 있다. Link source code는 "ns-2/tcl/libs/ns-lib.tcl"과 "ns-2/tcl/libs/ns-link.tcl" 파일에서 찾을 수 있다. 주목해야하는 하나는 당신이 lossy link(실제 user는 어떤 network object를 만들고 삽입할 수 있다.) 를 시뮬레이트 하기 위해서 link component 안에서 error module를 삽입할 수 있다. 이것을 어떻게 찾는가 하는 것은 NS document를 참고하라.




○ $ns queue-limit node1 node2 number:

이 라인은 상술된 숫자로 node1고 node2를 연결하는 두 개의 simplex link의 queue limit를 set한다. 이 점에서, 저자는 얼마나 많은 시뮬레이터 object의 member 함수의 종류들이 유용한지, 그리고 그것들이 무엇인지를 알지 못한다. "ns-2/tcl/libs/ns-lib.tcl"과 "ns-2/tcl/libs/ns-link.tcl"을 찾아보거나, 보다 자세한 정보를 찾으려면 NS document를 참고하라.




○ $ns duplex-link-op node1 node2...:

line의 다음 couple는 NAM display를 위해서 사용된다. 이 라인의 효과를 보기 위해서 user는 이 라인을 구성하고 시뮬레이션을 시도할 수 있다.


지금, 기본적인 network setup이 행해졌다. 다음에 해야할 일은 TCP와 UDP 같은 traffic agent, FTP와 CBR같은 traffic source를 setup하는 것이다. 그리고 그것들을 각각 node와 agent로 접속하는 것이다.




○ set tcp[new Agent/TCP]:

이 라인은 TCP agent를 생성하는 방법을 보여준다. 그러나, 일반적으로 user는 이런 방법으로 어떤 agent나 traffic source를 생성할 수 있다. Agent와 traffic source는 사실상 기본적인 object(not compound object)이며, 대부분 C++에서 구현되고 OTcl로 링크된다. 그러므로, 이러한 object instance를 생성하는 특수한 Simulator object member 함수는 없다. Agentsk traffic source를 생성하기 위해서, User는 object class 이름(Agent/TCP, Agent/TCPSink, Application/FTP 등등)을 알아야 한다. 이 정보는 NS document나 이 document에서 부분적으로 찾을 수 있다. 그러나, one shortcut는 "ns-2/tcl/libs/ns-default.tcl" file을 보는 것이다. 이 file은 가용한 network object에 대한 default 구성 parameter 값 setting을 포함한다. 그러므로, 그것은 어떤 종류의 network object가 NS에 유용한가 그리고 구성 parameter가 무엇인가에 대한 훌륭한 indicator로서 동작한다.




○ $ns attach-agent node agent:

attach-agent member 함수는 node object로 생성된 agent object를 접속한다. 실제적으로, 이 함수는 규정된 node의 attach member 함수를 호출한다. 그것은 그 자신으로 주어진 agent를 접속한다. 그러므로, user는 예를 들면, $n0 attach $tcp에 의해 동일한 일을 할 수 있다. 유사하게, 각 agent object는 그 자신으로 traffic source object를 접속하는 member 함수 attach-agent를 가진다.




○ $ns connect agent1 agent2:

서로간에 통신을 할 두 개의 agent가 생성된 후에, 다음 일은 그들 사이에 logical network 연결을 설정하는 것이다. 이 라인은 각기 다른 network와 port address pair로 목적지 address를 setting함으로서 network 연결을 설정한다.


network 구성이 모두 완료되었다고 가정하면, 다음에 해야할 일은 simulation 시나리오(시뮬레이션 scheduling 등)를 쓰는 일이다. Simulator object는 많은 scheduling member 함수를 갖는다. 그러나, 대부분 사용되는 방법은 다음과 같다.




○ $ns at time "string":

Simulator object의 member 함수는 주어진 simulation time에 규정된 string의 실행을 schedule하기 위해 scheduler(scheduler_ 는 script 시작 부분에서 [net scheduler] 명령에 의해 생성된 scheduler object를 지시하는 변수이다.)를 만든다. 예를 들어, $ns at 0.1 "$cbr start"는 data 전송을 위해 CBR을 시작하는 CBR traffic source object의 start member 함수를 호출하는 call를 만들 것이다. NS에서 보통 traffic source가 실제적인 data를 전송하지는 않지만 그것은 전송해야하는 data가 많으며, 전송할 data가 얼마나 많은지 알고 있다는 것을 기초적인 Agent에게 공지하고 packet을 생성하며 그것들을 전송한다.


모든 network 구성 후에, scheduling과 post-simulation 절차 specification이 행해진다. 남아있는 유일한 일은 시뮬레이션을 작동시키는 것이다. 이것은 $ns run으로 실행된다.

And

NS by Example - Network Components

|
사용자 삽입 이미지

Class Hierarchy (Partial)

 



1. Node and Routing

노드는 아래 그림과 같이 node entry object와 classifiers로 구성된 복합 object이다.
NS에는 두가지 타입의 노드가 있다.

[unicast node]
unicast routing과 port classifier의 역할을 하는 address classifier를 갖는다.

[multicast node]
unicast 패킷으로부터 multicast 패킷을 분류하고 classifier와 multicast routing을 수행하는 multicast classfier를 갖는다.

사용자 삽입 이미지

Node (Unicast and Multicast)


NS에서는 unicast node가 디폴트 노드이다. multicast node를 생성하기 위해 사용자는 OTcl 스크립트를 명확히 알아야 하며 scheduler object를 생성한후 모든 노드들은 multicast node로 생성되어야 한다. 노드 타입을 명확히 한후에 사용자는 디폴트로 사용하던것보다 구체적인 routing protocol을 선택할수 있다.

Unicast
- $ns rtproto [type]
- type : Static, Session, DV, cost, multi-path

Multicast
- $ns multicast (right after set $ns [new Scheduler])
- $ns mrtproto [type]
- type : CtrMcast, DM, ST, BST



2. Link

사용자가 simulator object의 멤버함수인 duplex-link를 사용하여 link를 생성하고자 할때, simplex links는 아래와 같이 생성된다.

사용자 삽입 이미지

Link


한가지 주의할 것은 노드의 output queue는 simplex link object의 일부분으로서 수행된다.
패킷은 link delay를 시뮬레이트하는 Delay object로 넘겨진 queue로부터 dequeue된다. 그리고 queue에서 drop된 패킷들은 Agent/Null로 보내지고 그곳에서 버려진다.
TTL object는 수신된 각 패킷을 위해 Time To Live 파라미터를 계산하고, 패킷의 TTL field를 업데이트한다.


Tracing

NS에서 네트워크의 활동은 simplex links 여기저기를 추적하는 일이다.
만약 시뮬레이터에서 네트워크의 행동을 추적하도록 지시되었다면($ns trace-all file or $ns namtrace-all file), links는 아래 그림에서 보듯이 그 명령이 trace object 다음에 온후에 생성된다. 사용자는 create-trace {type file src dst} 명령을 사용하여 주어진 source와 destination 노드간의 type 형태의 trace objects를 생성할수 있다.

사용자 삽입 이미지

Inserting Trace Objects


각 삽입된 trace object (i.e. EnqT, DeqT, DrpT and RecvT)가 패킷을 수신할때, 다른 어떤 시뮬레이션 시간 소비없이 명시된 trace file을 write하고, 패킷을 다음 네트워크 object에서 넘긴다.


Queue Monitor

근본적으로, tracing objects는 자신이 위치한곳에서 패킷의 도착시간을 기록하도록 고안되었다. 비록 사용자가 trace로부터 충분한 정보를 얻더라도, 누군가가 특정 output queue 내부에서 무엇이 진행중인지 알고싶어한다. 예를들어, RED queue행동에 관심있는 사용자가 평균 queue size의 dynamics(?)와 현재 특정 RED queue의 queue size를 측정하기 바랄수있다.
(즉, queue 모니터링이 필요하다) queue 모니터링은 다음그림과 같이 queue monitor objects와 snoop queue objects를 사용하여 이룰수 있다.

사용자 삽입 이미지

Monitoring Queue


패킷이 도착할때 snoop queue object는 이 상황을 queue monitor object에게 통보한다.
이러한 정보를 사용하는 queue monitor는 queue를 모니터한다.
snoop queue object는 그림에 나오진 않았지만, tracing object와 같이 사용할수 있다는걸 명심해라.



♡ Packet Flow Example

The network consist of two nodes (n0 and n1) of which the network addresses are 0 and 1 respectively. A TCP agent attached to n0 using port 0 communicates with a TCP sink object attached to n1 port 0. Finally, an FTP application (or traffic source) is attached to the TCP agent, asking to send some amount of data.

사용자 삽입 이미지

Packet Flow Example



Note that the above figure does not show the exact behavior of a FTP over TCP. It only shows the detailed internals of simulation network setup and a packet flow


And

802.11 MAC code in NS-2 (version 2.28)

|

[ Transport ]

Ns2 에서는 agent 개념으로 설명

패킷 생성, 전송, 수신 구현


1. TCP

지원 프로토콜 (교재 349P 참고/ 10.3)

1.1 이용 방법

  • 에이전트 생성
    • Set tcp [new Agent/TCP]         # 패킷 송신 에이전트를 변수 tcp로 지정
      _ Agent/TCP - a "tahoe" TCP sender
      _ Agent/TCP/Reno - a "Reno" TCP sender
      _ Agent/TCP/Newreno - Reno with a modification
      _ Agent/TCP/Sack1 - TCP with selective repeat (follows RFC2018)
      _ Agent/TCP/Vegas - TCP Vegas
      _ Agent/TCP/Fack - Reno TCP with "forward acknowledgment"
    • Set tcpsink [new Agent/TCPSink]    # 패킷 수신 에이전트를 변수 tcpsink로 지정
      _ Agent/TCPSink - TCP sink with one ACK per packet
      _ Agent/TCPSink/DelAck - TCP sink with configurable delay per ACK
      _ Agent/TCPSink/Sack1 - selective ACK sink (follows RFC2018)
      _ Agent/TCPSink/Sack1/DelAck - Sack1 with DelAck

  • 에이전트와 노드 결합
    • $ns attach-agent $n0 $tcp         #n0 노드에 tcp에이전트 결합
    • $ns attach-agent $n3 $sink        #n3 노드에 sink에이전트 결합

  • 에이전트끼리 연결
    • $ns connect $tcp $sink            #tcp 에이전트와 sink에이전트 연결

* Agent/TCP 와 Agent/TCPSink 한 쌍으로 설정 해야 함(교재 : 373p)


1.2 설정

[방법 1: simple configuration]

  • 에이전트 설정

set ns [new Simulator]

set node1 [$ns node]

set node2 [$ns node]


set tcp1 [$ns create-connection TCP $node1 TCPSink $node2 42]

$tcp set window_ 50


set ftp1 [new Application/FTP]

$ftp1 attach-agent $tcp1


$ns at 0.0 "$ftp start"

* set tcp1 [$ns create-connection TCP $node1 TCPSink $node2 42]

  1. create-connection 함수의 의미
  • TCP : 송신 에이젼트
  • $node1 : 송신 노드 (souce node)
  • TCPSink : 수신 에이젼트
  • $node2 : 수신 노드
  • 42 : flow ID

  • create-connection함수의 동작 순서
    • 두 에이전트 생성, 에이전트의 flow ID필드 설정
    • 송신 에이전트와 수신 에이전트를 알맞은 노드에 결합 시킨다
    • 에이전트 끼리 연결 한다.(송수신의 각 포트, 주소 설정)
    • create-connection 함수는 최종 결과값을 송신 에이전트가 생성될 때 사용한 이름인 tcp1로 반환 한다.
  • TDP 데이터 소스(Tcp Data Source)

    -데이터 생성모듈 ex) FTP, Telnet


[방법 2: 파라미터 직접 작성]

파라미터 (변수)

클래스 변수 : 전체 에이전트 값 변함 (ex: Agent/TCP set window_ 100)

인스턴스변수 : 해당 에이전트만 변함 (ex : $tcp set window_ 2.0 )

Agent/TCP set window_ 20 ;                # max bound on window size
Agent/TCP set windowInit_ 1 ;            # initial/reset value of cwnd
Agent/TCP set windowOption_ 1 ;            # cong avoid algorithm (1: standard)
Agent/TCP set windowConstant_ 4 ;            # used only when windowOption != 1
Agent/TCP set windowThresh_ 0.002 ;        # used in computing averaged window
Agent/TCP set overhead_ 0 ;            # !=0 adds random time between sends
Agent/TCP set ecn_ 0 ;                # TCP should react to ecn bit
Agent/TCP set packetSize_ 1000 ;           #
packet size used by sender (bytes)
Agent/TCP set bugFix_ true ;            # see explanation
Agent/TCP set slow_start_restart_ true ;   #
see explanation

Agent/TCP set tcpTick_ 0.1 ;        #
timer granulatiry in sec (.1 is NONSTANDARD)
Agent/TCP set maxrto_ 64 ;                # bound on RTO (seconds)
Agent/TCP set dupacks_ 0 ;                # duplicate ACK counter
Agent/TCP set ack_ 0 ;                #
highest ACK received

Agent/TCP set cwnd_ 0 ;                #
congestion window (packets)
Agent/TCP set awnd_ 0 ;                # averaged cwnd (experimental)
Agent/TCP set ssthresh_ 0 ;            # slow-stat threshold (packets)
Agent/TCP set rtt_ 0 ;                # rtt sample
Agent/TCP set srtt_ 0 ;                # smoothed (averaged) rtt
Agent/TCP set rttvar_ 0 ;                #
mean deviation of rtt samples
Agent/TCP set backoff_ 0 ;                # current RTO backoff factor
Agent/TCP set maxseq_ 0 ;                # max (packet) seq number sent


# set up TCP-level connections

$sink listen ;                # will figure out who its peer is

$src set window_ 100;

The creation of the FullTcp agent is similar to the other agents, but the sink is placed in a listening state by the listen method. Because a handle to the receiving side is required in order to make this call, the create-connection call used above cannot be used.


TCP 연결 예제 TCL

set tcp [new Agent/TCP] ;                         # create tcp agent
$ns_ attach-agent $node_(s1) $tcp ;           # bind src to node
$tcp set fid_ 0 ;                                         # set flow ID field
set ftp [new Application/FTP] ;                  # create ftp traffic
$ftp attach-agent $tcp ;                             # bind ftp traffic to tcp agent
set sink [new Agent/TCPSink] ;                # create tcpsink agent
$ns_ attach-agent $node_(k1) $sink ;         # bind sink to node
$sink set fid_ 0 ;                                       # set flow ID field
$ns_ connect $ftp $sink ;                          # active connection src to sink
$ns_ at $start-time "$ftp start" ;                  # start ftp flow

2. UDP

Agent/UDP와 agent/NULL을 한 쌍으로 함


[ Application ]

패킷 보내기

파라미터 정보 ./ns/tcl/lib/ns-default.tcl

CBR의 정보 : 교재 413p
(교재 : 배성수, "네트워크 시뮬레이터", 세화,2005)

1. Exponential

Exponential On/Off An Exponential On/Off object is embodied in the OTcl class Application/Traffic/Exponential. The

member variables that parameterize this object are:


packetSize_         the constant size of the packets generated
burst_time_         the average "on" time for the generator
idle_time_         the average "off" time for the generator
rate_             the sending rate during "on" times

Hence a new Exponential On/Off traffic generator can be created and parameterized as follows:

set e [new Application/Traffic/Exponential]
$e set packetSize_ 210
$e set burst_time_ 500ms
$e set idle_time_ 500ms
$e set rate_ 100k

NOTE: The Exponential On/Off generator can be configured to behave as a Poisson process by setting the variable burst_time_ to 0 and the variable rate_ to a very large value. The C++ code guarantees that even if the burst time is zero, at least one packet is sent. Additionally, the next interarrival time is the sum of the assumed packet transmission time (governed by the variable rate_) and the random variate corresponding to idle_time_. Therefore, to make the first term in the sum very small, make the burst rate very large so that the transmission time is negligible compared to the typical idle times.



2. CBR

A CBR object is embodied in the OTcl class Application/Traffic/CBR. The member variables that parameterize this

object are:

rate_         the sending rate
interval_     (Optional) interval between packets
packetSize_     the constant size of the packets generated
random_     flag indicating whether or not to introduce random "noise" in the scheduled departure times (default is off)
maxpkts_     the maximum number of packets to send (default is (228)

Hence a new CBR traffic generator can be created and parameterized as follows:

set e [new Application/Traffic/CBR]
$e set packetSize_ 48
$e set rate_ 64Kb
$e set random_ 1

The setting of a CBR object's rate_ and interval_ are mutually exclusive (the interval between packets is maintained as an interval variable in C++, and some example ns scripts specify an interval rather than a rate). In a simulation, either a rate or an interval (but not both) should be specified for a CBR object.



-예제 ?

set src [new Agent/UDP]
set sink [new Agent/UDP]
$ns_ attach-agent $node_(s1) $src
$ns_ attach-agent $node_(k1) $sink
$ns_ connect $src $sink

set e [new Application/Traffic/Exponential]
$e attach-agent $src
$e set packetSize_ 210
$e set burst_time_ 500ms
$e set idle_time_ 500ms
$e set rate_ 100k
$ns_ at 0.0 "$e start"



[Tips]


tr파일로 그래프 그리기

  raw2xg ?a xxx.tr > xxx.out

  xgraph xxx.out


nam. Tr. 파일 일괄 삭제 하는 스크립트 : Makefile 로 저장하기

[code type=c]

  default: clean

  clean:

      rm -f *~ *.tr *.nam

[/code]

정리 : 2006.12.11 by 임헌정
http://www.4ellene.net

And

802.11 MAC code in NS-2 (version 2.28)

|

802.11 MAC code in NS-2 (version 2.28)
by Joshua Robinson (jpr at rice.edu)
Last update: 4-29-05

Note that this document is no longer maintained, as I have stopped work on NS-2 as of 2005. Please do alert me if you find any errors or more up-to-date descriptions of the code.


There are 4 different paths the code can follow:

Transmitting a packet

Receiving a packet destined for itself

Overhearing a packet not destined for itself

Packets colliding


Or just jump to the listing of functions

or a list of the timers


Transmitting a packet

Roughly takes the following path (when no errors or congestion):

recv() -> send() -> sendDATA() and sendRTS() -> start defer timer

-> deferHandler() -> check_pktRTS() -> transmit()

-> recv() -> receive timer started

-> recv_timer() -> recvCTS() -> tx_resume() -> start defer timer -> rx_resume()

-> deferHandler() -> check_pktTx() -> transmit()

-> recv() -> receive timer started

-> recv_timer() -> recvACK() -> tx_resume() -> callback_ -> rx_resume() -> done!


When the first RTS fails:

recv() -> send() -> sendDATA() and sendRTS() -> start defer timer

-> deferHandler() -> check_pktRTS() -> transmit -> start send timer

-> send_timer() -> RetransmitRTS() -> tx_resume() -> backoff timer started

backoffHandler() -> check_pktRTS() -> transmit

the rest is the same as above


Receiving a packet

Roughly takes the following path (when no errors or congestion):

recv() -> receive timer started

-> recv_timer() -> recvRTS() -> sendCTS() -> tx_resume() -> start defer timer -> rx_resume()

-> deferHandler() -> check_pktCTRL() -> transmit()

-> recv() -> receive timer started

-> recv_timer() -> recvDATA() -> sendACK() -> tx_resume() -> start defer timer -> uptarget_->recv()

-> deferHandler() -> check_pktCTRL() -> transmit() -> start send timer

-> send_timer() -> tx_resume() <- nothing happens, we're done!


Functions

recv() (DOWN) - Like all connectors, which Mac inherits from, the packet to be sent is received by the recv() function. Because the recv() function is also called when a packet comes from the channel, recv() checks the direction field in the packet header. If the direction is DOWN, meaning the packet came from an upper layer, the packet is then passed on to the send() function.

recv() (UP) – The recv() function is called whenever a packet is received from either an upper or lower layer. If the packet is received from a lower layer – the network interface here, then the first check will be skipped. At this point the phy has just received the first bit of the incoming packet, but the MAC can't do anything with the packet until the whole packet is received. If the packet is received while the MAC is currently transmitting another packet, then the received packet would be ignored – meaning the error flag in the packet's header is set. If the MAC is not currently receiving any packets, then the rx_state_ is changed to RECV and checkBackoffTimer is called. Afterwards, the incoming packet is assigned to pktRx_ and the receive timer is started for the txtime() of the packet. If the MAC was already receiving a packet when this packet arrived, it will compare the received power of the new packet with the old packet. If the power of the new packet is smaller than the old packet by at least the capture threshold, the new packet will be ignored (captured) and the capture() function is called. If the power levels of the two packets are too close though, there will be a collision and control will transfer to collision(), which will drop the arriving packet. The original packet won't be dropped until it's reception is complete. Control will return to the MAC whenever the receive timer expires, calling recvHandler(), which in turns goes right to recv_timer().

send() - The send() function first checks the energy model, dropping the packet if the node is currently in sleep mode. It then sets callback_ to the handler passed along with the packet. This is so the handler can be called when the packet's transmission is complete. Next, send() calls sendDATA() and sendRTS which build the MAC header for the data packet and the RTS packet to go along with the data packet – which are stored in pktTx_ and pktRTS_ respectively. The MAC header for the data packet is then assigned a unique sequence number (with respect to the node).
Next, the MAC checks it's backoff timer. If the backoff timer is not currently counting down, then the node checks if the channel (medium) is idle, and if so the node will begin to defer. The node checks this using the function is_idle(). As per the 802.11 specs, the node will defer a difs time plus a randomly chosen amount of time in the interval [0, cw_), where cw_ is the current contention window. If the node is already waiting on it's defer timer, it will just continue waiting (not resetting the timer). If the medium is detected to be busy, then the node starts it's backoff timer. As of this point, the send() function has finished and control will resume when one of the timers expires, calling either deferHandler() or backoffHandler().

sendDATA() - This function builds the MAC header for the data packet. This involves increasing the size of the packet, setting the type as data, and subtype as data. The packet should now have a complete MAC header attached to it. The function then stores the txtime of the packet, which is computed by the txtime() function. By txtime, we basically mean the size of the packet multiplied by the Data rate. You'll notice (in 2.28 at least), that this calculation is done twice – this first time is just a waste. It's calculated again because a different value for the data rate is used if the packet happens to be a broadcast packet. Also, if the packet is not a broadcast packet, the duration field in the MAC header is computed. By duration, we mean the amount of time this communication still needs the channel after the data packet has been transmitted. For the case of a data packet, this corresponds to the amount of time to transmit an ACK plus a short inter-frame spacing. If the packet happens to be broadcast, this field is set to zero (no ACKs for broadcast packets). Now, the MAC has finished building the MAC header for the packet and finally assigns the internal variable pktTx_ to point to the packet we've been working on. This is essentially a way of storing the packet to be transmitted in a local buffer in the MAC. Now, the code returns to the send() function.

sendRTS() – This function is in charge of creating an RTS packet with the specified destination in conjunction with the data packet the MAC is trying to send. The first thing it does is check the size of the packet against the RTSThreshold. If the packet is smaller (or is broadcast) then no RTS is sent before the data is transmitted (the RTS/CTS mechanism is not used). In this case, the function simply returns control back to the send() function. Otherwise, a brand new packet is created (actually done in the first line of the function) and it's fields are set appropriately, i.e. the type is set as a MAC packet. A rts_frame structure is used to fill in the rest of the packet header and the appropriate values are put in the rts fields. The destination field is filled in with the parameter passed to the function and the rf_ta (source?) is filled in with the MAC's address. The duration field is also calculated as the time to transmit a CTS, the data packet (pktTx_) and an ACK (plus 3 sifs). After the RTS has been constructed, the internal state variable pktRTS_ is assigned a pointer to the new RTS. After this, control is returned to the send() function.

sendCTS() - This function is in charge of creating a CTS packet and pointing pktCTRL_ to it. Everything proceeds straightforwardly, with fields being given obvious values. The duration field is set to be the same as was in the RTS, except minus the txtime of a CTS and a sifs_ time, since that amount of time would have already elapsed once another station decoded the packet. After the creation of the CTS packet is done, pktCTRL_ is pointed to the new packet and control returns to recvRTS().

sendACK() - This function is responsible for creating an ACK packet to be sent in response to a data packet. The packet is created and all the fields are filled in with the obvious values. The duration field is set to zero indicating to other nodes that once this ACK has completed, they don't need to defer to another communication. Once the packet has been successfully built, pktCTRL_ is pointed to the new ACK and control returns to recvDATA().

deferHandler() - This function is called when the defer timer has expired. When this happens, this means the node has waited enough time before transmission to lessen the chance of collision and will now attempt to transmit a packet. Accordingly, the first thing the function does is assert that there is either a control, RTS, or data packet waiting to be transmitted. The function then calls check_pktCTRL(), and then makes sure the backoff timer is not currently running. Afterwards, it calls check_pktRTS() and check_pktTx(). If any of these check_ functions returns a value of zero, the defer handler stops, as this indicates that the check_ function has succeeded in transmitting that particular kind of packet. Therefore, the actual packet transmission is handled by one of these check_ functions. At this point, transmission has most likely begun on some kind of packet and control will resume at the expiration of the interface timer, txHandler(), which simply clears the flag tx_active_ to indicate that the phy is not currently transmitting something. Control will resume if another packet is received via recv(): a CTS if an RTS was just sent, a data packet if a CTS was just sent, or an ACK if a data packet was just sent. But control may also resume at the expiration of the send timer, sendHandler(), which immediately calls send_timer().

check_pktCTRL() - This function is responsible for transmitting CTS and ACK packets, which would be pointed to by pktCTRL_ . So the first thing the function does is check to see if this variable points to anything. If not, the function returns -1, indicating nothing was transmitted. The function will also return if the transmission state (tx_state_) indicates the MAC is currently transmitting either a CTS or ACK packet, although I don't know why this would occur. The function then performs a switch based on what kind of control packet is ready to be sent, CTS or ACK.
If it's a CTS, the MAC will check the status of the medium using is_idle(). If the channel is busy, the CTS will simply be dropped and pktCTRL_ set to zero. If the channel is idle, the function will, using macros, set the value of the tx_state_ to indicate the MAC is currently transmitting a CTS and then call the function checkBackoffTimer(). After this, the function calculates the timeout value – which is how long the MAC should wait before it decides the packet it sent wasn't received successfully. In the case that the control packet is an ACK, the MAC proceeds in the same way, except that it doesn't check the medium. Finally, the function transmit() is called with arguments pktCTRL_ and the previously calculated timeout value. At this point, the phy has just begun transmission of the control packet.

check_pktRTS() - This function, like the other two check_ functions, is responsible for transmitting a packet – in this case, an RTS packet. If there is no RTS packet ready to send, i.e. pktRTS_ is null, then the function simply returns with a value of -1, indicating that it did not send a packet. There is an oddly placed switch statement here presumably in order to detect an improperly built RTS packet. Before the RTS is sent, the channel is checked. If it is sensed to be busy, the contention window (cw_) is doubled using the inline function inc_cw() and the backoff timer is started again. The function therefore returns without transmitting a packet if the channel is busy. If the channel is idle, the tx_state_ of the MAC is set to RTS and the function checkBackoffTimer() is invoked. Next, the timeout value is calculated so that the MAC will know how long to wait for a CTS to be returned. Finally the function transmit() is called with arguments of the RTS packet and timeout value. At this point, the phy has begun transmission of the RTS packet.

check_pktTx() - This function, like the other two check_ functions, is responsible for transmitting a packet – in this case, the actual data packet. If there is no data packet waiting to be sent (pktTx_ is null), then the function returns with a value of -1, indicating that nothing was transmitted. Again, an oddly chosen switch statement is used to catch an improperly built data packet. If the channel is sensed to be busy, sendRTS is called. This means that despite the RTS/CTS exchange, another node is using the channel (possibly due to mobility), or RTS is not being used – in which case the sendRTS function will do nothing. Additionally, the contention window (cw_) is doubled using the inline function inc_cw() and then the backoff timer is started so that the MAC will remain idle until the other node has completed transmission. If the channel is idle, the tx_state_ is set to MAC_SEND and the checkBackoffTimer function is invoked. The timeout value is calculated in two ways, depending on whether or not the data packet is broadcast. If not, the timeout is how long the MAC should wait before it decides an ACK wasn't received. If the packet is broadcast, the timeout is simply the transmission time of the packet because no ACKs will be sent in conjunction with a broadcast packet. Finally, the function transmit() is invoked with arguments of the data packet and the calculated timeout value. At this point, the data packet has begun transmission.

checkBackoffTimer() - This inline function performs two checks. First, if the medium is idle and the backoff timer is currently paused, it will resume the timer.
The second check is if the medium is not idle and the backoff timer is currently running (busy and not paused), then it will pause the timer. This corresponds to the fact that the MAC only counts down it's backoff timer while the channel is idle. As per the specs, the timer should not be running while the channel is being used by another node.

transmit() – This function takes two arguments, a packet and a timeout value. It sets a flag variable, tx_active_, to one to indicate that the MAC is currently transmitting a packet. The function then performs a check because if it is an ACK being transmitted then it is possible that the node could be receiving a packet, in which case that packet would be missed. This next block checks if the MAC is currently receiving a packet and that it is an ACK being transmitted, and if so, marks the packet being received as having errors. Next, the packet is actually passed down to the network interface (WirelessPhy class) which is pointed to by downtarget_. Actually, only a copy of the packet is sent down in case there needs to be a retransmission. Finally, two timers are started – the send timer is started with the timeout value, which will alert the MAC that the transmission probably failed. Also, the interface timer(mhIF_) is started with the txtime() of the packet – when this timer expires, the MAC will know that the phy has completed the transmission of the packet.

send_timer() - This function is called at the expiration of the TxTimer, mhSend_. This timer expires after amount of time calculated as timeout in the corresponding check_ function – the expiration of this timer means slightly different things depending on which kind of packet was sent. In a switch statement, the MAC checks the value of tx_state_ to find out the kind of packet that was most recently sent and then handles each packet differently. If the last packet sent was an RTS, the expiration of the timer means a CTS wasn't received, presumably because the RTS collided or the receiving node is deferring. The MAC responds by attempting to retransmit the RTS in the function RetransmitRTS().
If the last packet sent was a CTS packet, the expiration of the timer means that no data packet was received. This is an infrequent event occurring if the CTS packet collided or if the data packet was in error. The MAC handles this by simply resetting itself to an idle state. This involves freeing the CTS packet stored in pktCTRL_.
If the last packet sent was a data packet, the expiration of the timer means that an ACK was not received. The MAC handles this situation by calling RetransmitDATA().
Finally, if the last packet sent was an ACK, the expiration of the timer simply means that the ACK has been transmitted, as no response is expected from an ACK. The MAC frees the ACK packet pointed to by pktCTRL_ .
After each case has been handled and a packet has possibly been prepared for retransmission, the function tx_resume() is given control. If a packet is going to be retransmitted, the backoff timer has already been started with an increased contention window.

RetransmitRTS() - This function is called in response to a CTS not being received after an RTS was sent. First, the function does some stat collecting, recording this as a failed RTS, and the short retry count (ssrc_) is incremented. The short retry count is maintained so the MAC knows when to give up on this packet and drop it, which happens when ssrc_ reaches the value of ShortRetryLimit in the MAC MIB. The drop is handled by called the discard() function on the RTS packet and resetting the pktRTS_ pointer to zero. Then the data packet is also dropped by calling the same discard() function. The ssrc_ is reset to zero and the contention window is reset to it's initial value. Otherwise, the same RTS pointed to by pktRTS_ is kept, but a retry field in the RTS is incremented. Because of the contention avoidance mechanism, the contention window is doubled and then the backoff timer is started using this new contention window. This means control will eventually return to backoffHandler().

RetransmitDATA() - This function is called when an ACK is not received in response to a data packet being sent. If the data packet was a broadcast packet, an ACK shouldn't be expected and so the data packet is treated as being successfully transmitted and so is freed and the congestion window reset. The backoff counter is started though, I'm not really sure why. Two separate retry counts are maintained depending on whether or not an RTS is being used for this data packet. If an RTS is not being used, the short retry limit is used, otherwise the long retry limit is used as a threshold. If the retry count has exceeded the threshold, then the data packet is discarded using the discard() function and the retry count and congestion window are reset. If the retry count has not been exceeded, the data packet is prepared for retransmission by incrementing a retry field in the mac header, doubling the congestion window, and then starting the backoff timer. This means control will eventually return to backoffHandler().

tx_resume() - This function is called when the MAC is getting ready to send a packet but needs to set some timers. If a control packet (CTS or ACK) is waiting to be sent, this function simply starts the defer time for a sifs_ amount of time. This is because a node is supposed to wait a brief period of time before transmitting. If an RTS packet is waiting to be sent, then the MAC makes sure the backoff timer isn't currently busy – if it is, then the MAC will wait to start the defer timer. If the backoff timer isn't busy the defer timer is started for a random time in the interval [0,cw_) plus a difs_ time. If a data packet is next to be sent, and MAC isn't currently backing off, then the defer timer is started for the data packet. If an RTS wasn't used for this packet, then the defer timer is set for a random value in the interval [0,cw_] plus a difs_ time, but if an RTS was used, the MAC will only defer for a sifs_ time. This is because if an RTS was used, then the channel has already been reserved for this MAC and it shouldn't need to worry about collisions.
If there are no packets waiting to be sent, but the callback_ is defined, then it is handled, corresponding to a successfully completed packet transmission. Finally, the tx_state_ is set to idle. Control will return back to the MAC when the defer timer has expired, deferHandler() - or back to the function that called it, like one of the recvP functions.

capture() - This function is called when a second packet is received while the MAC is currently receiving another packet, but the second packet is weak enough so that the phy can ignore it. The important thing this function does is update the NAV so that carrier sense will know that the channel is still busy after it has finished receiving it's packet. Capture also discards the captured packet.

collision() - The collision handler first checks the rx_state_ variable and sets it to MAC_COLL in case this is the first collision during the current packet. If a third packet collides, rx_state_ will already be MAC_COLL. Then, the MAC calculates how much longer the new packet will last and how much longer the old packet will last. If the new packet will last longer, then the MAC makes the new packet pktRx_ and resets the receive timer, mhRecv_. In this case the old packet is discarded here, but if the old packet will last longer then the new packet is simply discarded and pktTx_ doesn't change. So at the end of this function, the colliding packet that would have completed first has been discarded and rx_state_ is set to MAC_COLL.

recv_timer() - This is the receive timer handler, called when mhRecv_ expires (though indirectly though RecvHandler). The expiration of the receive timer means that a packet has been fully received and can now be acted upon. First, the MAC checks to see if it's currently transmitting a packet by checking the flag, tx_active_. If so, the MAC wouldn't not have even heard the packet so it is just discarded (without updating NAV). Next, the rx_state_ is checked to see if there was a collision during this packet, i.e. rx_state_ equals MAC_COLL. If so, then pktRx_ is the colliding packet that lasted longest and now needs to be discarded. The NAV is also set for an eifs_ time, which is the amount of time the MAC must wait after a collision. The MAC then checks the packet for errors, and discards the packet if any were detected. Again, the NAV is set for eifs_ time after the error packet is finished being received. The next check the MAC performs is if the packet is actually destined for itself – if not, the MAC updates the NAV for the value in the duration field in the MAC header (not necessary just the txtime of the packet). This is of course so that the MAC doesn't attempt to transmit while other nodes are using the channel. The next check consists of sending the packet to any taps if it is a data packet – essentially sending the packet to anybody wanting to listen in promiscuous mode. The next check involves the adaptive fidelity algorithm and basically keeping track of the nodes within radio range of the node. And finally, the last check performed is address filtering, where all packets that are not destined for the current node are discarded. The NAV would have already been updated so there's no need to do anything else with the packet.
Now the MAC decides what to do based on what kind of packet it just received. If the packet is of MAC_Type_Management, it's simply dropped. If it's an RTS packet, recvRTS() is called, if CTS or ACK, then recvCTS() or recvACK() is called. And not surprisingly, if it's a data packet, then recvDATA() is called. After this, pktRx_ is set to zero and control to given to rx_resume().

recvRTS() - This function is called by recv_timer after a full RTS packet has been received. If the tx_state_ is not idle, then the packet wouldn't have been heard, so it's simply discarded. Also, if the MAC is currently responding to another node (pktCTRL_ is nonzero) then the RTS will be ignored. This happens for example, if the node already heard an RTS from another node is waiting to send a CTS back. Otherwise, the MAC is in a state such that it can receive a packet, so it prepares to send a CTS by calling sendCTS(). Next, the MAC stops the defer time and calls tx_resume() - which will restart the defer timer for the appropriate amount of time. Control then returns to recv_timer().

recvCTS() - This function is called by the recv_timer after a full CTS packet has been received, meaning the MAC can now send it's data. Since the MAC has no use for the RTS packet it just transmitted, it's freed and pktRTS_ is set to zero. The send timer is stopped, although I'm not exactly sure why it would be running. Control then goes straight to tx_resume(), which sets the defer timer, and then control finally returns back to recv_timer().

recvACK() - This function is called by the recv_timer after a full ACK packet has been received, indicating a successful data transmission. First, the MAC checks that it really did just sent a data packet (tx_state == MAC_SEND) and discards the ACK if it didn't. The MAC now knows that it just succesfully transmitted it's data packet, so it frees pktTx_ and sets it to zero. The send timer is also stopped, but again, I don't know why. The MAC then resets the appropriate retry count, short if an RTS wasn't used, long if it was. Also, the congestion window is reset and the MAC starts its backoff timer so it won't just immediately send again. Control then goes to tx_resume() and then back to recv_timer(). In tx_resume(), since there are no packets ready to send, the callback will be invoked, effectively telling the interface queue to send down another packet for transmission.

recvDATA() - This function is called by the recv_timer after a full data packet has been received, indicating that this node just successfully received a data packet. First, the MAC strips the MAC header from the packet, getting it ready to be sent to the upper layers. If the data packet wasn't broadcast, RTS packets are being used, and tx_state_ indicates that the last packet the MAC sent was a CTS, then that CTS (pktCTRL_) is cleaned up (freed and pktCTRL_ set to zero). And again, the send timer is stopped. If the MAC didn't just send a CTS when it should have, the data packet is dropped because events didn't happen in the right order and the function returns. Otherwise, the data packet was received correctly and the MAC prepares to send an ACK by calling sendACK() and then tx_resume() to start the defer timer appropriately. If a CTS was not sent (because there was no corresponding RTS), then the MAC checks pktCTRL_. If there is a control packet there, the MAC will drop the data packet because there is no room to buffer an ACK packet (the ACK would go in pktCTRL_). Otherwise, sendACK() is called to create an ACK packet to send. In this case, if the send timer isn't currently counting down, tx_resume() is called to start the defer timer.
Next, the MAC updates it's sequence number cache – if the packet is unicast only. The packet is checked to make sure the source node will fit in the cache – it is possible for the cache to have been configured with an incorrect size, i.e. less than the total number of nodes in the system. Then the sequence number of the packet just received is compared with the most recently received sequence number and if they match, the data packet is discarded as it is a duplicate (same packet received twice). If the source node is not in the cache (cache is too small), some warnings are printed out.
The data packet is then passed to the uptarget_ - the layer above the MAC (usually link-layer). This means the data packet has been fully received by the node and it's on it's way up the protocol stack.

rx_resume() - This simple function is called after recv_timer has completed. All it does is set the rx_state_ to idle and then invoke checkBackoffTimer().

backoffHandler() - This function is called whenever the backoff timer expires. This function first checks to see whether there is a control packet (CTS or ACK) waiting to be sent. If so, it makes sure that the MAC is either sending the packet or deferring before sending the packet. If there was no control packet, check_pktRTS() is called. If there was no RTS packet, then check_pktTx() is called. This means, that at the expiration of the backoff timer, an RTS or a data packet will be transmitted if either is waiting. I think this should only happen on RTS or data retransmissions.

txHandler() - Handler for IFTimer that simply clears a flag in the MAC to indicate that the radio is no longer active.

command() - The command() function is a TCL hook for all the classes in ns-2 which allows C++ functions to be called from a TCL script. The arguments for command() are effectively the same as for the main function is basic C programs, with argc and argv containing the command given to the object. In the 802.11 MAC, this function is not often used, at least in my experience. If none of the commands match those specific to the 802.11 MAC, then the command() function of the parent class is called.



Timers
The timers are defined in the files mac/mac-timers.h/cc while the handlers (functions called when the timer expires) are in mac-802_11.cc.

IFTimer – The interface timer keeps tracks of how long the interface will be in transmit mode. This is only the time when the interface is actively transmitting bits into the air. The handler for this timer is txHandler(). Probably the simplest timer used by the MAC layer.

NavTimer &ndash Started at the reception of a packet for the length of time indicated in the duration field of the MAC header. Calls navHandler() on expiration.

RxTimer &ndash Started when the first bit of a packet is received and set for the length of time the packet will require to be completely received. This timer is needed because in simulation the entire packet is available as soon as the first bit arrives, but the MAC should not access the packet until it would have been completely received in reality. In the case of a packet collision, the receive timer is reset to expire at the end of the last colliding packet. The timer indirectly calls recv_timer() on expiration by calling recvHandler() first.

TxTimer &ndash Indicates the time by which an ACK/CTS should have been received. The TxTimer (mhSend_) is started when a packet is transmitted by the transmit() function. Each type of packet has an expected response, for example, an RTS packet expects a CTS packet to follow. The timer is therefore stopped when a CTS, data, or ACK packet is received. The timer is not started on transmission of an ACK packet as there is no response expected. On expiration, send_timer() is called indirectly by first calling the (ahem, worthless) function sendHandler().

DeferTimer &ndash

BackoffTimer &ndash

BeaconTimer &ndash Not used.


And

NS2_Reno, cwnd, ip packet size의 11Mbps 무선랜, 100Mbps유선랜 ns2_upstream10/downstream10

|

Phy/WirelessPhy set CPThresh_ 10.0
Phy/WirelessPhy set CSThresh_ 3.1622777e-14
Phy/WirelessPhy set RXThresh_ 3.1622777e-13
Phy/WirelessPhy set bandwidth_ 11Mb
Phy/WirelessPhy set Pt_ 0.031622777
Phy/WirelessPhy set freq_ 2.472e9
Phy/WirelessPhy set L_ 1.0
#######################################

set opt(chan)           Channel/WirelessChannel    ;# channel type
set opt(prop)           Propagation/TwoRayGround   ;# radio-propagation model
set opt(netif)          Phy/WirelessPhy            ;# network interface type
set opt(mac)            Mac/802_11                 ;# MAC type
#set opt(ifq)            Queue/DropTail/PriQueue    ;# interface queue type
set opt(ifq)  CMUPriQueue
set opt(ll)             LL                         ;# link layer type
set opt(ant)            Antenna/OmniAntenna        ;# antenna model
set opt(ifqlen)         [lindex $argv 1]                         ;# max packet in ifq
set opt(data)             [lindex $argv 0]                         ;# number of mobilenodes
set opt(nm)             [expr $opt(data)]                         ;# number of mobilenodes
set opt(adhocRouting)   DSDV                       ;# routing protocol
#set opt(adhocRouting)   DumbAgent   ;#KDH

set opt(cp)             ""                         ;# connection pattern file
#set opt(sc)     "../mobility/scene/scen-3-test"    ;# node movement file.
set opt(sc)             ""          ;#KDH

set opt(x)      670                            ;# x coordinate of topology
set opt(y)      670                            ;# y coordinate of topology
set opt(seed)   0.0                            ;# seed for random number gen.
set opt(stop)   500                            ;# time to stop simulation
set packetSize_ 1500                           ;#packet size
set cwnd_ 64
set opt(ftp0-start)      90.0         ;
Mac/802_11 set dataRate_ 11.0e6
#set num_wired_nodes      5
set opt(nw)      [expr $opt(nm) + 1]   ;
set num_bs_nodes         1                     ;

# ============================================================================
# check for boundary parameters and random seed
if { $opt(x) == 0 || $opt(y) == 0 } {
 puts "No X-Y boundary values given for wireless topology\n"
}
if {$opt(seed) > 0} {
 puts "Seeding Random number generator with $opt(seed)\n"
 ns-random $opt(seed)
}

# create simulator instance
set ns_   [new Simulator]

# set up for hierarchical routing
$ns_ node-config -addressType hierarchical
AddrParams set domain_num_ 2           ;# number of domains
lappend cluster_num 1 1                ;# number of clusters in each domain
AddrParams set cluster_num_ $cluster_num
lappend eilastlevel $opt(nw) $opt(nw)               ;# number of nodes in each cluster
AddrParams set nodes_num_ $eilastlevel ;# of each domain

set tracefd  [open up_down_stream_$opt(nm)-$opt(nm).tr w]
$ns_ trace-all $tracefd

# Create topography object
set topo   [new Topography]

# define topology
$topo load_flatgrid $opt(x) $opt(y)

# create God
create-god [expr $opt(nm) + $num_bs_nodes]

#create wired nodes
set temp {0.0.0 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8 0.0.9 0.0.10 0.0.11 0.0.12 0.0.13 0.0.14 0.0.15 0.0.16 0.0.17 0.0.18 0.0.19 0.0.20  0.0.21 0.0.22 0.0.23 0.0.24 0.0.25 0.0.26 0.0.27 0.0.28}        ;# hierarchical addresses for wired domain
for {set i 0} {$i < $opt(nw)} {incr i} {
    set W($i) [$ns_ node [lindex $temp $i]]
}

# configure for base-station node
$ns_ node-config -adhocRouting $opt(adhocRouting) \
                 -llType $opt(ll) \
                 -macType $opt(mac) \
                 -ifqType $opt(ifq) \
                 -ifqLen $opt(ifqlen) \
                 -antType $opt(ant) \
                 -propType $opt(prop) \
                 -phyType $opt(netif) \
                 -channelType $opt(chan) \
   -topoInstance $topo \
                 -wiredRouting ON \
   -agentTrace ON \
                 -routerTrace OFF \
                 -macTrace OFF


#create base-station node
set temp {1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28} ;# hier address to be used for wireless
                                     ;# domain
set BS(0) [$ns_ node [lindex $temp 0]]
$BS(0) random-motion 0               ;# disable random motion

# create mobilenodes in the same domain as BS(0) 
# note the position and movement of mobilenodes is as defined
# in $opt(sc)

#configure for mobilenodes
$ns_ node-config -wiredRouting OFF

  for {set j 0} {$j < $opt(nm)} {incr j} {
    set node_($j) [ $ns_ node [lindex $temp \
     [expr $j+1]] ]
    $node_($j) base-station [AddrParams addr2id \
     [$BS(0) node-addr]]
}

#create links between wired and BS nodes

for {set t 0} {$t < $opt(nm) } {incr t} {
$ns_ duplex-link $W($opt(nm)) $W($t) 100Mb 20ms DropTail
}
$ns_ duplex-link $W($opt(nm)) $BS(0) 100Mb 50ms DropTail
# setup TCP connections

#Agent/UDP set packetSize_ 1048
for {set ttt 0} {$ttt < $opt(nm) } {incr ttt} {
 set tcp_($ttt) [new Agent/TCP/Reno]
 $tcp_($ttt) set fid_ 2
 set sink_($ttt) [new Agent/TCPSink]
 $ns_ attach-agent $W($ttt) $tcp_($ttt)
 $ns_ attach-agent $node_($ttt) $sink_($ttt)
 $ns_ connect $tcp_($ttt) $sink_($ttt)
 set ftp_($ttt) [new Application/FTP]
 $ftp_($ttt) attach-agent $tcp_($ttt)
 $ns_ at $opt(ftp0-start) "$ftp_($ttt) start"

}

for {set tttt 0} {$tttt < $opt(nm)} {incr tttt} {
 set tcp_($tttt) [new Agent/TCP/Reno]
 $tcp_($tttt) set fid_ 2
 set sink_($tttt) [new Agent/TCPSink]
 $ns_ attach-agent $node_($tttt) $tcp_($tttt)
 $ns_ attach-agent $W($tttt) $sink_($tttt)
 $ns_ connect $tcp_($tttt) $sink_($tttt)
 set ftp_($tttt) [new Application/FTP]
 $ftp_($tttt) attach-agent $tcp_($tttt)
 $ns_ at $opt(ftp0-start) "$ftp_($tttt) start"

}

# Tell all nodes when the simulation ends
for {set i } {$i < $opt(nm) } {incr i} {
    $ns_ at $opt(stop).0 "$node_($i) reset";
}
$ns_ at $opt(stop).0 "$BS(0) reset";

$ns_ at $opt(stop).0002 "puts \"NS EXITING...\" ; $ns_ halt"
$ns_ at $opt(stop).0001 "stop"
proc stop {} {
    global ns_ tracefd
    close $tracefd
}

# informative headers for CMUTracefile
puts $tracefd "M 0.0 nn $opt(nm) x $opt(x) y $opt(y) rp \
 $opt(adhocRouting)"
puts $tracefd "M 0.0 sc $opt(sc) cp $opt(cp) seed $opt(seed)"
puts $tracefd "M 0.0 prop $opt(prop) ant $opt(ant)"

puts "Starting Simulation..."
$ns_ run


And

NS2_스크립트 up_down_stream2.sh_upstream10/downstream10

|

#!/bin/sh
echo "Awk ShellScript"
num=1
num1=1
rm -rf up_down.send_wireless up_down.rec_wireless up_down.send_wire up_down.rec_wire
rm -rf up_down.ACK_wireless up_down.ACK_wire
rm -rf up_down.UDP_th
    
for Tcl_file in  "1 10" "2 10" "3 10" "4 10" "5 10" "6 10" "7 10" "8 10" "9 10" "10 10"
do
 set $Tcl_file
 echo "###################### TCL" $num
  nsp up_down_stream.tcl $1 $2
 num=`expr $num + 1`
done
for PacketSize in  1 2 3 4 5 6 7 8 9 10
do
 echo "###################### TCL_Mobile_change" $num1
 echo "awk -f awk-ack_rec_wire  up_down_stream_$PacketSize-$PacketSize.tr >> testbook"
 sed 's/_/ /' up_down_stream_$PacketSize-$PacketSize.tr > testbook
 echo "awk -f awk-ack_rec_wire  testbook >> up_down_stream_$PacketSize-$PacketSize.tr "
 sed 's/_/ /' testbook > up_down_stream_$PacketSize-$PacketSize.tr
 rm -rf testbook
done

for PacketSize in  1 2 3 4 5 6 7 8 9 10
do
  echo "###################### ACK" $num1
  echo "awk -f awk-ack_rec_wire  up_down_stream_$PacketSize-$PacketSize.tr >> up_down.rec_wire"
  awk -f awk-ack_rec_wire -v data=$PacketSize up_down_stream_$PacketSize-$PacketSize.tr >> up_down.rec_wire
  echo "awk -f awk-ack_send_wire  up_down_stream_$PacketSize-$PacketSize.tr >> up_down.send_wire"
  awk -f awk-ack_send_wire -v data=$PacketSize up_down_stream_$PacketSize-$PacketSize.tr >> up_down.send_wire
  echo "awk -f awk-ack_rec_wireless up_down_stream_$PacketSize-$PacketSize.tr >> up_down.rec_wireless"
  awk -f awk-ack_rec_wireless -v data=$PacketSize up_down_stream_$PacketSize-$PacketSize.tr >> up_down.rec_wireless
  echo "awk -f awk-ack_send_wireless  up_down_stream_$PacketSize-$PacketSize.tr >> up_down.send_wireless"
  awk -f awk-ack_send_wireless -v data=$PacketSize up_down_stream_$PacketSize-$PacketSize.tr >> up_down.send_wireless
 
  echo "###################### Throughput" $num1
  echo "awk -f awk-throughput  up_down_stream_$PacketSize-$PacketSize.tr >> up_down.ACK_wireless"
  awk -f awk-throughput  -v nn=$PacketSize up_down_stream_$PacketSize-$PacketSize.tr >> up_down.ACK_wireless
  echo "awk -f awk-throughput1  up_down_stream_$PacketSize-$PacketSize.tr >> up_down.ACK_wire"
  awk -f awk-throughput1 -v nn=$PacketSize up_down_stream_$PacketSize-$PacketSize.tr >> up_down.ACK_wire
 
  echo "###################### UDP Throughput" $num1
  echo "awk -f awk-UDP -v rt=$PacketSize up_down_stream_$PacketSize-$PacketSize.tr >> up_down.UDP_th"
  awk -f awk-UDP -v rt=$PacketSize up_down_stream_$PacketSize-$PacketSize.tr >> up_down.UDP_th
  num1=`expr $num1 + 1`
 
done



And

NS2_awk-ack_rec_wire_upstream10/downstream10

|

BEGIN {
 n=0;
 total1 = 0;
 total2 = 0;
 total3 = 0;
 total4 = 0;
 total5 = 0;
 total6 = 0;
 total7 = 0;
 total8 = 0;
 total9 = 0;
 total10 = 0;
 throughput=0;
 
 SIMUL_TIME=500;
 AWK_INTERVAL=400;
 
}

{
 
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="0") ) {
   if (n == 0) start = $2;
   total1 ++;
   end = $2;
  }if (1<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="1") ) {
   if (n == 0) start = $2;
   total2 ++;
   end = $2;
  }if (2<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="2") ) {
   if (n == 0) start = $2;
   total3 ++;
   end = $2;
  }if (3<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="3") ) {
   if (n == 0) start = $2;
   total4 ++;
   end = $2;
  }if (4<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="4") ) {
   if (n == 0) start = $2;
   total5 ++;
   end = $2;
  }if (5<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="5") ) {
   if (n == 0) start = $2;
   total6 ++;
   end = $2;
  }if (6<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="6") ) {
   if (n == 0) start = $2;
   total7 ++;
   end = $2;
  }if (7<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="7") ) {
   if (n == 0) start = $2;
   total8 ++;
   end = $2;
  }if (8<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="8") ) {
   if (n == 0) start = $2;
   total9 ++;
   end = $2;
  }if (9<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($4 =="9") ) {
   if (n == 0) start = $2;
   total10 ++;
   end = $2;
  }
  }
  }
  }
  }
  }
  }
  }
  }
  }
 
}

END { 
 print total1;
 print total2;
 print total3;
 print total4;
 print total5;
 print total6;
 print total7;
 print total8;
 print total9;
 print total10;
        print "============================================================";
}

And

NS2_awk-ack_rec_wireless_upstream10/downstream10

|

BEGIN {
 
 total0 = 0;
 total1 = 0;
 total2 = 0;
 total3 = 0;
 total4 = 0;
 total5 = 0;
 total6 = 0;
 total7 = 0;
 total8 = 0;
 total9 = 0;
 
 nm0=(data+2);
 nm1=(data+3);
 nm2=(data+4);
 nm3=(data+5);
 nm4=(data+6);
 nm5=(data+7);
 nm6=(data+8);
 nm7=(data+9);
 nm8=(data+10);
 nm9=(data+11);
 
 SIMUL_TIME=500;
 AWK_INTERVAL=400;
}

{
   if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm0)) {
   if (n0 == 0) start0 = $2;
  
   total0 ++;
   end0 = $2;
  }
   if (1<data)
  {
  if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm1 )) {
   if (n1 == 0) start1 = $2;
  
   total1 ++;
   end1 = $2;
  }
  if (2<data)
  {
  if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm2  )) {
   if (n2 == 0) start2 = $2;
  
   total2 ++;
   end2 = $2;
  }
  if (3<data)
  {
  if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm3)) {
   if (n3 == 0) start3 = $2;
  
   total3 ++;
   end3 = $2;
  }
  if (4<data)
  {
  if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm4) ) {
   if (n4 == 0) start4 = $2;
  
   total4 ++;
   end4 = $2;
  }
  if (5<data)
  {
  if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm5) ) {
   if (n5 == 0) start5 = $2;
  
   total5 ++;
   end5 = $2;
  }
  if (6<data)
  {
  if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm6) ) {
   if (n6 == 0) start6 = $2;
  
   total6 ++;
   end6 = $2;
  }
  if (7<data)
  {
  if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm7) ) {
   if (n7 == 0) start7 = $2;
  
   total7 ++;
   end7 = $2;
  }
  if (8<data)
  {
  if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm8) ) {
   if (n8 == 0) start8 = $2;
  
   total8 ++;
   end8 = $2;
  }
  if (9<data)
  {
  if ( ($1 =="r") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm9) ) {
   if (n9 == 0) start9 = $2;
  
   total9 ++;
   end9 = $2;
  }
  }
  }
  }
  }
  }
  }
  }
  }
  }
}

END {
 
 print total0;
 print total1;
 print total2;
 print total3;
 print total4;
 print total5;
 print total6;
 print total7;
 print total8;
 print total9;
print "============================================================";
}


And

NS2_awk-ack_send_wire_upstream10/downstream10

|

BEGIN {
 n=0;
 total0 = 0;
 total1 = 0;
 total2 = 0;
 total3 = 0;
 total4 = 0;
 total5 = 0;
 total6 = 0;
 total7 = 0;
 total8 = 0;
 total9 = 0;
 throughput=0;
 
 SIMUL_TIME=500;
 AWK_INTERVAL=400;
 
}

{
 if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="0") ) {
   if (n == 0) start = $2;
   total0 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (1<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="1") ) {
   if (n == 0) start = $2;
   total1 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (2<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="2") ) {
   if (n == 0) start = $2;
   total2 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (3<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="3") ) {
   if (n == 0) start = $2;
   total3 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (4<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="4") ) {
   if (n == 0) start = $2;
   total4 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (5<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="5") ) {
   if (n == 0) start = $2;
   total5 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (6<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="6") ) {
   if (n == 0) start = $2;
   total6 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (7<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="7") ) {
   if (n == 0) start = $2;
   total7 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (8<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="8") ) {
   if (n == 0) start = $2;
   total8 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (9<data)
  {
  if ( ($1 =="r") && ($5 =="ack") &&  ($3 =="9") ) {
   if (n == 0) start = $2;
   total9 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  }
  }
  }
  }
  }
  }
  }
  }
  }
}

END {
 
 print total0;
 print total1;
 print total2;
 print total3;
 print total4;
 print total5;
 print total6;
 print total7;
 print total8;
 print total9;
print "============================================================";
 

}


And

NS2_awk-ack_send_wireless_upstream10/downstream10

|

BEGIN {
 n=0;
 total0 = 0;
 total1 = 0;
 total2 = 0;
 total3 = 0;
 total4 = 0;
 total5 = 0;
 total6 = 0;
 total7 = 0;
 total8 = 0;
 total9 = 0;
 throughput=0;
 nm=data;
 SIMUL_TIME=500;
 AWK_INTERVAL=400;
}

{
 if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == nm+2)) {
   if (n == 0) start = $2;
   total0 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (1<nm)
  {
  if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == (nm + 3))) {
   if (n == 0) start = $2;
   total1 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (2<nm)
  {
  if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == (nm + 4))) {
   if (n == 0) start = $2;
   total2 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (3<nm)
  {
  if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == (nm + 5))) {
   if (n == 0) start = $2;
   total3 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (4<nm)
  {
  if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == (nm + 6)) ) {
   if (n == 0) start = $2;
   total4 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (5<nm)
  {
  if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == (nm + 7)) ) {
   if (n == 0) start = $2;
   total5 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (6<nm)
  {
  if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == (nm + 8)) ) {
   if (n == 0) start = $2;
   total6 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (7<nm)
  {
  if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == (nm + 9)) ) {
   if (n == 0) start = $2;
   total7 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (8<nm)
  {
  if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == (nm + 10)) ) {
   if (n == 0) start = $2;
   total8 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  if (9<nm)
  {
  if ( ($1 =="s") && ($4 =="AGT") && ($7 =="ack") && ($3 == (nm + 11)) ) {
   if (n == 0) start = $2;
   total9 ++;
   n +=1;
   #print n,"\t",$0;
   end = $2;
  }
  }
  }
  }
  }
  }
  }
  }
  }
  }
}

END {
 print total0;
 print total1;
 print total2;
 print total3;
 print total4;
 print total5;
 print total6;
 print total7;
 print total8;
 print total9;
print "============================================================";
}


And