반응형

Host OS: Ubuntu 16.04 (amd64)

Host Spec (VM): Quad core 2.6GHz (Intel Zeon, Haswell), 4GB RAM

LXC template: ubuntu



지난 여름에는 라즈베리파이 4개를 가지고 무선 메쉬 네트워크를 만들고, 각각의 라즈베리파이가 AP 역할을 함으로써 서로 다른 AP에 물린 클라이언트들 사이에 통신이 되도록 하였고, 이를 중개하는 multi-constrained 라우팅 프로토콜을 Java로 개발해서 테스트를 했었다.


사실 성능을 생각하면 C로 개발해야 하지만 무지막지하게 늘어나는 개발 시간 때문에 그나마 익숙하게 다룰 수 있는 Java로 개발을 했었고, 이제 와서 보니 이게 ns-3에서 시뮬레이션을 돌릴 때 결국 C나 파이썬으로 포팅해야 되는 어려움으로 돌아오고 말았다. ㄷㄷ


하지만 ns-3는 real-world program을 돌릴 수 있는 몇 가지 방법을 제시하고 있었고, 그 중에서 Linux Container (LXC)를 이용한 방법이 있어서 튜토리얼을 따라하며 환경을 구축해 보았다.


실제로 예제를 그대로 따라해서 2개의 노드가 IEEE 802.11g로 서로 애드혹 네트워크로 연결되고 각각의 노드에서 ping, ssh 등을 테스트하는 데에는 아무 문제가 없었다.

여기서 더 나가서 내가 개발한 Java 기반의 라우팅 프로토콜을 실행시키는 과정이 생각보다 오래 걸렸지만, 이것도 각 컨테이너를 인터넷에 먼저 연결시키고 apt-get으로 필요한 패키지를 다 설치하고 나니 어쨌든 내가 라즈베리파이에서 돌리던 모양 그대로 실행시킬 수 있었다.


여기까지는 일단 그대로 실행이 되는지부터 봐야 해서 노드 3개까지만 만들어서 해 본 거였고, 이제 본격적으로 시뮬레이션을 돌리기 위해서 노드 생성과 Java 프로그램 실행을 자동화하는 스크립팅 작업을 했는데 이것 또한 시간이 은근히 많이 걸렸다. ㅜㅜ


우여곡절 끝에 이제 내가 마음대로 원하는 만큼의 노드(컨테이너)를 자동으로 생성/실행할 수 있게 되었고, 네트워크 토폴로지는 ns-3에서 역시나 마음대로 설정해 주면 되었다.


드디어 대망의 첫 실험...

자신있게 10개의 노드를 명령어 한 줄로 간지나게(?) 자동으로 뙇 생성하고, 토폴로지는 4-4-2 그리드 형태로 만든 다음, 실험 시작을 누르고 나서 시범적으로 9번 노드에서 이웃 노드인 10번 노드한테 ping을 날려 봤더니...


root@node9:/# ping 10.0.0.10

PING 10.0.0.10 (10.0.0.10) 56(84) bytes of data.

64 bytes from 10.0.0.10: icmp_seq=1 ttl=64 time=3665 ms

64 bytes from 10.0.0.10: icmp_seq=2 ttl=64 time=4356 ms

64 bytes from 10.0.0.10: icmp_seq=3 ttl=64 time=5375 ms

64 bytes from 10.0.0.10: icmp_seq=4 ttl=64 time=7245 ms

64 bytes from 10.0.0.10: icmp_seq=5 ttl=64 time=8166 ms

64 bytes from 10.0.0.10: icmp_seq=6 ttl=64 time=9149 ms

64 bytes from 10.0.0.10: icmp_seq=7 ttl=64 time=10225 ms

64 bytes from 10.0.0.10: icmp_seq=8 ttl=64 time=11106 ms

64 bytes from 10.0.0.10: icmp_seq=9 ttl=64 time=12252 ms

64 bytes from 10.0.0.10: icmp_seq=10 ttl=64 time=13146 ms

64 bytes from 10.0.0.10: icmp_seq=11 ttl=64 time=14062 ms

64 bytes from 10.0.0.10: icmp_seq=12 ttl=64 time=15261 ms

64 bytes from 10.0.0.10: icmp_seq=13 ttl=64 time=16784 ms

64 bytes from 10.0.0.10: icmp_seq=14 ttl=64 time=18056 ms

64 bytes from 10.0.0.10: icmp_seq=15 ttl=64 time=19286 ms

64 bytes from 10.0.0.10: icmp_seq=16 ttl=64 time=20347 ms

64 bytes from 10.0.0.10: icmp_seq=17 ttl=64 time=21576 ms

64 bytes from 10.0.0.10: icmp_seq=18 ttl=64 time=22208 ms

64 bytes from 10.0.0.10: icmp_seq=19 ttl=64 time=22970 ms

64 bytes from 10.0.0.10: icmp_seq=20 ttl=64 time=23673 ms

64 bytes from 10.0.0.10: icmp_seq=21 ttl=64 time=24549 ms

64 bytes from 10.0.0.10: icmp_seq=22 ttl=64 time=24565 ms

64 bytes from 10.0.0.10: icmp_seq=23 ttl=64 time=24311 ms

64 bytes from 10.0.0.10: icmp_seq=24 ttl=64 time=24205 ms

64 bytes from 10.0.0.10: icmp_seq=25 ttl=64 time=23996 ms

64 bytes from 10.0.0.10: icmp_seq=26 ttl=64 time=23627 ms

64 bytes from 10.0.0.10: icmp_seq=27 ttl=64 time=23452 ms

64 bytes from 10.0.0.10: icmp_seq=28 ttl=64 time=23325 ms

64 bytes from 10.0.0.10: icmp_seq=29 ttl=64 time=23048 ms

64 bytes from 10.0.0.10: icmp_seq=30 ttl=64 time=22669 ms

64 bytes from 10.0.0.10: icmp_seq=31 ttl=64 time=22337 ms

64 bytes from 10.0.0.10: icmp_seq=32 ttl=64 time=21869 ms

64 bytes from 10.0.0.10: icmp_seq=33 ttl=64 time=21127 ms

64 bytes from 10.0.0.10: icmp_seq=34 ttl=64 time=20186 ms

64 bytes from 10.0.0.10: icmp_seq=35 ttl=64 time=19246 ms

64 bytes from 10.0.0.10: icmp_seq=36 ttl=64 time=18327 ms

64 bytes from 10.0.0.10: icmp_seq=37 ttl=64 time=17383 ms

64 bytes from 10.0.0.10: icmp_seq=38 ttl=64 time=16449 ms

64 bytes from 10.0.0.10: icmp_seq=39 ttl=64 time=15512 ms

64 bytes from 10.0.0.10: icmp_seq=40 ttl=64 time=14573 ms

64 bytes from 10.0.0.10: icmp_seq=41 ttl=64 time=13607 ms

64 bytes from 10.0.0.10: icmp_seq=42 ttl=64 time=12676 ms

64 bytes from 10.0.0.10: icmp_seq=43 ttl=64 time=11745 ms

64 bytes from 10.0.0.10: icmp_seq=44 ttl=64 time=10816 ms

64 bytes from 10.0.0.10: icmp_seq=45 ttl=64 time=9876 ms

64 bytes from 10.0.0.10: icmp_seq=46 ttl=64 time=8953 ms

64 bytes from 10.0.0.10: icmp_seq=47 ttl=64 time=8012 ms

64 bytes from 10.0.0.10: icmp_seq=48 ttl=64 time=7037 ms

64 bytes from 10.0.0.10: icmp_seq=49 ttl=64 time=6042 ms

64 bytes from 10.0.0.10: icmp_seq=50 ttl=64 time=5064 ms

64 bytes from 10.0.0.10: icmp_seq=51 ttl=64 time=4069 ms

64 bytes from 10.0.0.10: icmp_seq=52 ttl=64 time=3074 ms

64 bytes from 10.0.0.10: icmp_seq=53 ttl=64 time=2080 ms

64 bytes from 10.0.0.10: icmp_seq=54 ttl=64 time=1087 ms

64 bytes from 10.0.0.10: icmp_seq=55 ttl=64 time=102 ms

64 bytes from 10.0.0.10: icmp_seq=56 ttl=64 time=5.94 ms

64 bytes from 10.0.0.10: icmp_seq=57 ttl=64 time=5.57 ms

64 bytes from 10.0.0.10: icmp_seq=58 ttl=64 time=5.82 ms

64 bytes from 10.0.0.10: icmp_seq=59 ttl=64 time=5.49 ms

64 bytes from 10.0.0.10: icmp_seq=60 ttl=64 time=5.55 ms

^C

--- 10.0.0.10 ping statistics ---

60 packets transmitted, 60 received, 0% packet loss, time 59063ms

rtt min/avg/max/mdev = 5.498/13466.053/24565.805/8177.166 ms, pipe 25

root@node9:/# 



Aㅏ...

저기 중간에 점도 찍히지 않고 당당하게 5자리를 찍어주는 저 결과는 뭥미?

24205는 뭔가요? 저게 진정 와이파이 RTT인가여? 털썩...


각 컨테이너에서 아무 프로그램도 돌고 있지 않을 때는 이웃노드 간에 ping을 날리면 약 5ms가 되어야 정상인데, 보는 것처럼 데이터 패킷도 아닌 ICMP 패킷 하나가 바로 옆으로 가는 데 24초를 넘어섰다. ㄷㄷㄷ 저것도 계속 RTT가 커지기만 하길래 24초쯤 되는 상황에서 돌아가는 모든 Java 프로그램을 죽였더니, 한참이 지나고 나서야 ping이 정상으로 돌아온 것이다.


내가 Java 프로그램을 잘못 만들었구나 자책하려고 했지만, Host 머신에서 CPU 사용량을 확인해 보니 ns-3 프로세스가 혼자 97% ~ 110% 사이를 왔다갔다 하고 있었고, 정작 내가 개발한 Java 프로세스들은 별로 CPU를 차지하고 있지 않았다. (라즈베리파이2에서도 3-9% 수준이긴 했음)


일차적으로 생각해 본 원인은 ns-3 프로세스가 L2 이하를 시뮬레이션 시키고 있는데, 10개의 노드 각각이 라우팅을 위해서 Hello 패킷을 비롯한 컨트롤 패킷을 매 초마다 발생시키니까 싱글 코어만으로는 계산하는 양이 감당이 안돼서 응답이 늦어지는 바람에 ping이 20초를 넘어서는 저런 사단이 난 것 같았다.


아~망했어요 ㅠㅠ

나는 ns-3 코어가 적어도 100노드 정도의 scalability는 책임질 수 있을 거라 생각했는데... 이건 뭐 컨테이너가 제아무리 가벼워도 각자 발생시키는 패킷의 양이 늘어나면 ns-3 코어가 감당을 못하는 상황이라니...


현재까지는 ns-3에 멀티코어 활용하도록 고친다던지, 아예 컨테이너도 없이 real-world 프로그램을 직접 네트워크와 연동하는 방법(DCE라고 하는데... 결국 컨테이너로 해결을 못하면 이것도 공부해야 함...)은 아직 확인하지 못했다.


내가 ns-3에 멀티코어 활용 방법을 아직 몰라서 이런 것이라고 믿고 싶다. ㅜㅜ 

그런데 왠지 보니까 기본적으로 멀티코어를 활용하도록 설계했을 법도 한데 안한 점과 구글 검색(ns-3 multi core)에서 첫 페이지에서 그런 옵션을 켜는 법이라던지 하는 간단한 해결방법이 보이지 않는 것을 보면... 


야~신난다 @_@

대안으로 나온 것이 컨테이너도 없이 DCE라고 직접 프로그램 코드를 바로 실행하는 방법도 있지만 이건 C++만 된다고 한다. DCE에 Java 프로그램을 붙이는 방법이 있는지 찾아보고, 이마저도 없으면 쌩으로 Java를 모두 C++ 또는 파이썬으로 포팅하는 대규모 토건사업이 펼쳐지겠지 ㄹㅇㅁㄴㄹㅇㅁㄹㅁㅈ 일자리 창출 인정? =_=


정신줄 그만 놓고, 해결 방법을 찾아봐야겠다. ㅜㅜ


반응형
블로그 이미지

Bryan_

,