제 4 장 SJMAC NS2(Network Simulator) 모듈 구현

1. Wiress LAN을 구성하는 각 모듈의 역할 및 관계

Network Simulator에서 네트워크 스택의 각 층을 담당하고 있는 모듈로는 LL(Link-Layer), ARP, IFq, MAC, Radio Propagation Model, Channel등이 있으며 각 모듈의 역할 및 관계는 각각 [표 4-1], [그림 4-1]과 같다.

모듈이름	모 듈 역 할
Src/Sink	FTP 모듈이나 트래픽 생성기과 같이 프레임을 수신하는 최상의 계층 혹은 프레임을 처음으로 생성하는 최상위 계층을 시뮬레이션하는 모듈이다.
RTagent	라우팅 프로토콜을 시뮬레이션하기 위한 모듈이다. 현재 SJMAC에서는 DSDV 라우팅 프로토콜을 사용하고 있다.
LL	Link-Layer는 데이터 링크 프로토콜(data link protocols) 시뮬레이션을 담당한다. 패킷의 분할과 조합 그리고 신뢰성 있는 링크 프로토콜등 많은 프로토콜들이 LL에 구현되어 있다.
ARP	각 노드에 할당되어진 IP address를 가지고 physical address를 알아내는 역할을 담당한다.
IFq	IFq는 보내거나 혹은 받은 패킷을 큐에 임시로 저장하는 역할을 담당한다. 즉 네트워크를 통해서 패킷이 송신되고 있는 동안 윗 계층에서 내려오는 패킷들을 저장하는 버퍼역할을 담당한다.
MAC	MAC(Medium Assess Protocols)의 역할을 담당하는 모듈이다. MAC 부분은 실제 전송측과 받는측 2부분으로 나누어진다. 전송측은 MAC헤더의 추가와 channel의 패킷전달을 담당하며 받는측은 physical layer에서 오는 패킷을 비동기적인 방법으로 받고, 받은 패킷들을 link-layer 모듈로 전달하는 역할을 한다. 본 프로젝트에서는 wiress lan의 성능을 개선하기 위하여 SJMAC 모듈을 구한하고 기존의 MAC 모듈을 대체하였다.
Radio Propagation Model	노드가 다른 노드에게 패킷을 전송하기 원할 때 그 패킷이 전송 되어질 수 있는 거리를 계산하는 역할을 담당한다.
Channel	Channel 모듈은 실제 physical layer의 패킷 전송을 시뮬레이션하는 역할을 담당한다. Contention mechanisms(경쟁 방식)을 위해 shared medium이 구현되어 있다.

[표 4-1] Network Simulator의 Wiress LAN을 구성하는 각 모듈의 역할

[그림 4-1]은 Wiress LAN 모듈을 구성하는 각 구성모듈들의 관계를 나타내고 있다. Src 모듈에서 생성되어진 프레임은 LL, IFq, MAC, NetIF 모듈을 거쳐 마지막으로 channel모듈을 통해서 다른 노드에게로 전송되어진다. channel모듈을 통해서 이러한 프레임을 전송받은 다른 노드는 NetIF, MAC, IFq, LL 순으로 전달되고 최종적으로 Sink모듈에 전달되기 전에 전송되어진 프레임의 목적지 주소와 자신의 주소를 addr demux와 port demux로 비교한다. 비교결과 주소가 일치한다면 Sink모듈로 프레임이 전달되지만 만약 두 주소가 다르다면 RTagent 모듈을 통해서 프레임을 목적지까지 전달하기 위한 다음경로의 노드주소를 알아내어 프레임을 전달한다.

[그림 4-1] NS2-2.27에서의 무선LAN 전체 모듈구조

2. SJMAC Simulation Model

SJMAC 프로토콜을 시뮬레이션하기 위해서는 앞에서 설명한 Wiress LAN와 관련되어진 각 모듈들이 모두 필요하지만 이번절에서는 기존의 802.11e를 개선하기 위하여 수정되어진 모듈들만을 설명하고 802.11e와 SJMAC에 공통적으로 구현되어진 부분에 대한 설명은 생략하도록 하겠다. 802.11e 모듈에서 SJMAC으로의 구현상의 주요 변화는 MAC 계층을 시뮬레이션하는 모듈에서 대부분 이루어진다. 그러므로 이번절에서는 MAC 계층과 관련되어진 모듈을 위주로 설명하도록 하겠다.

NS2는 싱글스레드 가상 이벤트 기반 프로그래밍 방식이기 때문에 SJMAC 모듈에서는 패킷 송수신의 시작, 완료 혹은 충돌감지등의 이벤트를 위해서는 이벤트들을 관리하는 가상타이머가 필요하다. 다음은 SJMAC에서 사용되어지는 가상타이머로는 defer timer, backoff timer, interface timer, send timer, nav timer이 있다.

● Defer Timer : SJMAC이 매체가 사용중이지 않다는 것을 감지하기 위해서 DIFS기간만큼 기다리거나 SIFS기간 동안 기다리기 위해서 사용되어지는 타이머이다.

● Backoff Timer : backoff timer는 자신의 전송차례를 기다리기 위해 남아 있는 시간을 계산하는데 사용된다.

● Interface Timer : interface timer는 얼마나 오랫동안 패킷을 전송할지를 결정하는데 사용되는 타이머이다.

● Send Timer : 패킷을 전송하고 얼마나 오랫동안 응답을 기다릴지 계산하는 타이머이다. 즉 send timer가 종료를 알리는 이벤트를 발생하면 패킷전송이 타임아웃 되었다는 것을 나타낸다.

● Nav Timer : 노드가 얼마나 오랫동안 nav 상태에 있어야 하는지를 계산하는 타이머이다. Nav timer가 종료되어야만 노드는 패킷 전송을 재시도 할 수 있다.

각 타이머는 클래스로 구현되어지고 start, stop, pause, resume, handle 함수를 가지고 있다. Start 함수는 타이머와 관련된 이벤트를 스케쥴러에 추가하여 일정한 시간이 지나면 이벤트가 실행될수 있도록 한다. Stop 함수는 start함수에 의해서 스케쥴러에 등록된 타이머 이벤트를 취소한다. Pause 함수는 일정시간동안 스케쥴러에 등록된 이벤트를 정지시키며, handle함수는 NS 스케쥴러에서 꺼내어진 이벤트를 처리하기 위한 함수를 가리킨다. 이러한 SJMAC 타이머에 대한 구현은 ../ns-2.27/mac/mac-timers-JMAC.cc/h에서 찾을 수 있다.

SJMAC 프로토콜을 시뮬레이션하기 위한 모듈은 Mac802_11_JMAC 클래스에 의해서 구현되었으며, MAC802_11_JMAC 클래스는 ../ns-2.27/mac/mac-802_11_JMAC.cc/h에서 찾을 수 있다. MAC802_11_JAMC을 구성하는 멤버함수와 변수에 대한 설명은 다음 표와 같다.

구 성 요 소	의 미	사 용 예
멤버 함수
Mac802_11_JMAC()	멤버 변수들을 초기화하고 SJMAC을 다른 계층의 모듈과 연결해 준다.
recv()	MAC계층으로 패킷이 들어올 때 제일 처음으로 호출되어지는 함수 이다. 윗계층(IFq)에서 내려오는 패킷은 적절한 처리를 하여 아래계층(NetIF)으로 전달하고 아래계층에서 전달된 패킷은 윗계층으로 전달한다.	recv(packet, handler)
hdr_dst()	hdr헤더에서 패킷의 destination주소를 알아내 dst에 저장하여 반환한다.	hdr_dst(hdr, dst)
hdr_src()	hdr헤더에서 패킷의 source주소를 알아내 src에 저장하여 반환한다.	hdr_src(hdr, src)
hdr_type()	hdr헤더에서 패킷의 type을 알아내 type에 저장하여 반환한다.	hdr_type(hdr, type)
backoffHandler()	backoff timer에 의해서 호출된다. backoff로 설정한 시간이 지나면 노드가 RTS, DATA 패킷을 전송하기 위해 호출하는 함수이다. pri를 우선순위를 가지는 패킷을 전송한다.	backoffHandler(pri)
navHandler()	nav timer에 의해서 호출된다. nav로 설장한 시간이 지나면 노드는 RTS, DATA 패킷을 전송할 수 있는 기회를 얻기 위해 backoff timer를 다시 시작시킨다.	navHandler()
recvHandler()	패킷수신을 완료하였을 때 호출되는 함수이다. 단순히 recv_timer() 함수를 다시 호출한다.	recvHandler()
sendHandler()	패킷전송시에 타임 아웃이 발생하면 호출되는 함수 이다. 단순히 send_timer() 함수를 다시 호출한다.	sendHandler()
txHandler()	패킷전송을 완료하였을 때 호출되는 함수이다. 현재 노드의 상태를 IDLE상태로 변환한다.	txHandler()
deferHandler()	RTS, CTS, DATA, ACK 패킷을 전송하기 원할때 DIFS 혹인 SIFS기간 만큼 기다려야 한다. deferHandler은 defer timer에 의해서 설정된 DIFS, SIFS 시간이 지나면 호출된다. 패킷전송을 위한 처리가 이루어진다.	deferHandler(pri)
recv_timer()	패킷수신을 완료하였을때 recvHandler 함수에 의해서 호출되는 함수이다. 수신한 패킷의 종류에 따라 recvRTS, recvCTS, recvDATA, recvACK 함수중에 하나를 호출한다. 또한 패킷의 에러와 충돌을 검사한다.	recv_timer()
구 성 요 소	의 미	사 용 예
send_timer()	패킷전송시에 타임아웃이 발생되면 sendHandler 함수에 의해서 호출되는 함수이다. 전송하려던 패킷의 종류에 따라 RTS 혹은 DATA를 재전송한다.	send_timer()
send()	윗계층으로 부터 전달받은 패킷을 아래계층으로 전달하기 위해 호출되는 함수이다.	send(packet, handler)
check_pktCTRL()	CTS, ACK 패킷을 전송할 수 있는지 여부를 검사하고, 전송할 수 있다고 판단되면 아래계층으로 CTS, ACK 패킷을 전달한다.	check_pktCTRL()
check_pktRTS()	RTS 패킷을 전송할 수 있는지 여부를 검사하고, 전송할 수 있다고 판단되면 아래계층으로 RTS 패킷을 전달한다.	check_pktRTS()
chekc_pktTx()	DATA 패킷을 전송할 수 있는지 여부를 검사하고, 전송할 수 있다고 판단되면 아래계층으로 DATA 패킷을 전달한다.	chekc_pktTx()
sendRTS()	RTS 패킷을 전송하기 위해서 새로운 RTS 패킷을 생성하고 전송시간을 설정한다.	sendRTS(pri, dst)
sendCTS()	CTS 패킷을 전송하기 위해서 새로운 CTS 패킷을 생성 하고 전송시간을 설정한다.	sendCTS(pri, dst)
sendDATA()	윗계층으로부터 전달받은 DATA 패킷을 전송하기 위해서 DATA 패킷에 전송시간을 설정한다.	sendDATA(pri, packet)
sendACK()	ACK 패킷을 전송하기 위해서 새로운 ACK 패킷을 생성 하고 전송시간을 설정한다.	sendACK(pri, dst)
RetransmitDATA()	DATA 패킷을 재전송하기 위해서 호출되는 함수이다.	RetransmitDATA(pri)
RetransmitRTS()	RTS 패킷을 재전송하기 위해서 호출되는 함수이다.	RetransmitRTS(pri)
recvRTS()	RTS 패킷의 수신을 완료한 이후의 처리를 하기 위해 호출되는 함수이다.	recvRTS(packet)
recvCTS()	CTS 패킷의 수신을 완료한 이후의 처리를 하기 위해 호출되는 함수이다.	recvCTS(packet)
recvDATA()	DATA 패킷의 수신을 완료한 이후의 처리를 하기 위해 호출되는 함수이다.	recvDATA(packet)
recvACK()	ACK 패킷의 수신을 완료한 이후의 처리를 하기 위해 호출되는 함수이다.	recvACK(packet)
collision()	패킷충돌이 발생하였을때 호출되는 함수이다. 충돌된 패킷은 모두 discard() 함수에 의해서 버려진다.	collision(packet)
구 성 요 소	의 미	사 용 예
discard()	인수로 받은 packet를 버린다. packet를 버린다는 것은 packet에 할당되어진 메모리를 다른 곳에서 재사용 할 수 있도록 설정하는 것을 의미한다.	discard(packet)
rx_resume()	노드가 다른 패킷을 수신할 수 노드의 상태를 IDLE로 변환한다.	rx_resume()
tx_resume()	노드가 다른 패킷을 송신할 수 노드의 상태를 IDLE로 변환한다.	tx_resume()
txtime()	패킷의 전송시간을 계산하여 반환한다.	txtime(packet) txtime(psz, drt)
transmit()	패킷을 다른 노드로 전송하기 위해서 아래계층으로 전달한다.	transmit(packet, timeout)
setRxState()	수신상태를 변환한다.	setRxState(newstate)
setTxState()	송신상태를 변환한다.	setTxState(newstate)
inc_cw()	Contention Window의 크기를 증가시킨다.	inc_cw(pri)
rst_cw()	Contention Window의 크기를 최소값으로 초기화한다.	rst_cw(pri)
sec()	마이크로초를 초로 변환한다.	sec(time)
usec()	초를 마이크로초로 변환한다.	usec(time)
set_nav()	마이크로 초 단위로 노드의 nav를 설정한다.	set_nav(time)
getAIFS()	pri에 해당하는 AIFS시간을 구한다.	getAIFS(pri)
getCW()	pri에 해당하는 CW시간을 구한다.	getCW(pri)
getPF()	pri에 해당하는 PF시간을 구한다.	getPF(pri)
sendJamming()	src에서 dst로 패킷을 안전하게 송수신 하기위해서Jamming 신호를 생성하는 함수이다..	sendJamming(src, dst, duration)
멤버 변수
phymib_	물리적 계층과 관련된 정보를 가지고 있는 멤버변수이다. 물리적 계층에서 추가되는 헤더의 크기등과 같은 정보가 저장된다.
macmib_	MAC 계층과 관련된 정보를 가지고 있는 멤버변수이다. SIFS, DIFS 기간의 길이등을 저장한다.
basicRate_	RTS, CTS, ACK 패킷을 전송할 때 사용되는 rate이다.
dataRate_	DATA 패킷을 전송할 때 사용되는 rate이다.
mhIF	interface timer 역할을 담당하는 타이머 변수이다.
mhNav	nav timer 역할을 담당하는 타이머 변수이다.
mhRecv_	rx timer 역할을 담당하는 타이머 변수이다.
mhSend_	tx timer 역할을 담당하는 타이머 변수이다.
mhDefer_	defer timer 역할을 담당하는 타이머 변수이다.
구 성 요 소	의 미	사 용 예
mhBackoff_	backoff timer 역할을 담당하는 타이머 변수이다.
nav_	nav가 종료되는 시점을 저장하고 있는 변수이다.
rx_state_	노드의 수신상태를 저장하는 변수이다.
tx_active_	노드가 송신하고 있는지를 저장하는 변수이다.
tx_state_	노드의 송신상태를 저장하는 변수이다.
pktRTS_	현재 송신중인 RTS 패킷을 저장하는 변수이다.
pktCTRL_	현재 송신중인 CTS, ACK 패킷을 저장하는 변수이다.
pktTx_	현재 송신중인 DATA 패킷을 저장하는 변수이다.
pktRx_	현재 수신중인 패킷을 저장하는 변수이다.
cwmin_	Contention Window의 최소크기를 저장하는 변수이다.
cw_max	Contention Window의 최대크기를 저장하는 변수이다.
aifs_	각 우선순위별로 aifs기간을 저장하고 있는 변수이다.