반응형

OS: Ubuntu 18.04
Simulator: ns-3.30

 

ns-3에서 무선 채널을 통해 두 노드가 서로 unicast로 패킷을 보낼 때, 시뮬레이션 타임을 기준으로 완전히 똑같은 시간에 패킷을 보내면 (즉, ns3::Socket::Send 함수를 똑같은 시간에 사용하면) 충돌이 발생한다.
이것을 방지하려면 패킷을 보낼 때 의도적으로 약간의 지터(jitter)를 부여하면 되는데, 예를 들면 두 노드가 ns3::Socket::Send를 call할 때, 수십~수백 마이크로초(microseconds) 정도의 차이만 있어도 무선 채널에서 충돌로 인한 패킷 유실을 피할 수 있다.

이를 위해 각 노드에서 Socket::Send 함수를 call 하는 부분 앞에 매번 지터를 아래와 같이 넣어 주었다.

Ptr<UniformRandomVariable> rng = CreateObject<UniformRandomVariable> ();
uint32_t jitter = rng->GetInteger(0, 1000);
Simulator::Schedule(jitter, &패킷_보내는_함수, 함수 파라미터, ...);

문제는 위와 같이 지터를 넣어 주는데도 영문도 모르게 패킷이 전달이 안되는 것이다.

분명히 동일한 시간에 패킷을 보내지만 않으면 서로 모두 전달이 되는데도 불구하고, bootstrap처럼 자동으로 주기적으로 heartbeat 메세지를 보내도록 설정하면, 패킷이 이유 없이 사라지는 것이었다. 보내는 노드에서 Socket::Send 함수를 call 한 기록만 있고 패킷을 받은 노드가 하나도 없는 상황...

 

UniformRandomVariable 클래스를 다시 확인해 보니, GetInteger 함수는 "다음(next)" 랜덤 값을 반환한다고 되어 있다. 그 말은, 랜덤 숫자의 배열을 미리 생성해 놓고, 맨 첫번째 인덱스부터 시작해서 GetInteger 함수를 call할 때마다 순서대로 하나씩 반환한다는 뜻이다.

내가 동시에 모든 노드가 시뮬레이션 시작 시간에 동시에 heartbeat 메세지를 생성해서 broadcast하도록 스케줄링을 걸었고, 그 스케줄링 함수 안에 Socket::Send 함수 앞에 GetInteger를 썼다. 내가 랜덤에 시드 값을 지정하지 않았기 때문에, 모든 노드가 같은 타이밍에 GetInteger를 맨 처음 불러왔다면, 모두가 똑같은 jitter 숫자를 가져온다는 뜻이므로, 랜덤을 잘못 적용한 셈이다. ㅠㅠ

 

각 노드별로 노드 ID 숫자를 seed로 입력해 주었더니, 모두가 처음으로 받아 오는 GetInteger 값이 다 다른 숫자가 되었다. 이제서야 진짜 랜덤으로 작동한 것이다.

#include "ns3/random-variable-stream.h"

// ...(중략)

SeedManager::SetSeed(node_id + 1); // ns-3에서 node id는 0부터 시작하고, 

                                                                            // Seed 값에 0이 들어가면 런타임 에러가 나서 1을 더해 줬다.

Ptr<UniformRandomVariable> rng = CreateObject<UniformRandomVariable> ();

 

 

반응형
블로그 이미지

Bryan_

,