DTV 에서 사용하는 모든 네트워크 상태를 관장하는 NM(=Networkmanger) 에 대해서 설명한다.
Version | Date | Comment | Author |
1.0 | 2011-1-31 | 최초 작성 | 연구7실 AP 그룹 김우종 주임연구원 |
본 문서는 모든 네트워크 상황에 대해 관장하는 Middleware 인 NM 의 모든 것에 대해서 다룬다. 이 문서를 통해 DTV 에서의 네트워크 동작과 이를 이용한 서비스들(ex: Broadband)의 동작을 좀더 쉽게 이해할 수 있고 나아가서는 이를 디버깅 및 기능 개선을 하는데 소요되는 시간을 줄일 수 있을 것이라 기대한다.
소스코드와 API 함수 표기는 굴림 글꼴로 표시한다.
내용 중 알아두면 편리한 참고 사항과 반드시 알아야 하는 중요 사항을 다음과 같이 표시한다.
<Note> | 내용 중 알아두면 편리한 각종 참고 사항 |
<Caution> | 내용 중 반드시 알아야 하는 중요한 사항 |
본 문서는 다음과 같은 약어를 사용한다.
Acronym | Description |
NM | Networkmanager |
NM 은 DTV 에서 유/무선 네트워크의 설정, 접속등을 관리한다. 랜선이 꼽히거나, WiFi 로 AP 에 접속할 때 모두 NM 의 동작을 거친다. 위로는 UI 와 아래로는 Wired/Wireless Driver 와 정보를 주고 받는다. 추가로 dhcp client 기능도 가진다.
NM 은 독립적인 프로세스로 동작한다.
코드는 src/mw/nm 디렉토리 아래에 있다. 크게 API 와 NM 두 부분으로 나눌 수 있다.
API 는 NM 과 통신하기 위해서 필요한 함수들의 모음이고, NM 은 Networkmanager 자체를 말한다.
현재 디렉토리 구조는 다음과 같다.
이름 | 설명 |
adapt | Task, Message, Debug 관련한 API 가 정의되어 있다. 실제 DTV 에서 Debug 를 제외하고는 여기서 선언한 API 를 사용하지 않는다 |
networkmanager | NM 이 동작하면서 사용하는 함수가 정의되어 있다. 빌드하면, Networkmanager 파일이 생성된다. |
src | NM 과 통신하기 위해서 필요한 API 가 정의되어 있다. DTV 빌드 시, 함께 빌드된다. |
※ nm_basic, nm_netcard 로 디렉토리가 분리되어 있는 것은 중국향에 대응되는 3G netcard 라는 모듈 때문이다. 실제로 NM 빌드 후에 아래와 같이 2개의 오브젝트 파일이 생성된다.
앞서 말했듯이 NM 은 각각 API 와 NM 두 부분으로 나뉘어지기 때문에, src 와 networkmanager 디렉토리 아래에 basic, netcard 라는 디렉토리가 분리되어 있는 것이다. 이후 빌드 시에 바이너리에 따라 서로 다른 파일을 컴파일하게 된다.
예를 들어 중국향 cfg 를 사용하여 epk 를 빌드한다면, 'Networkmanager.netcard' 파일이 포함되어 생성될 것이다. 그외의 향에서는 'Networkmanager.basic' 파일이 포함된다.
NM 을 사용하기 위해서는 2번 빌드를 해야 한다. 첫번째는 NM 자체 바이너리를 생성할 때이고, 두번째는 NM 과 통신하기 위해 API 를 빌드하여 링킹시킬 때 이다(DTV 빌드 시).
NM 이라고 하는 별도의 프로그램을 빌드한다고 생각하면 된다. nm/networkmanager 아래의 Makefile 에 의해 빌드된다. 빌드되는 각 파일은 아래와 같다.
이름 | 설명 |
brcm_priv.c | Broadcom 에서 제공하는 DDI 를 정의(Chip 에 의존적임) |
wifi_ddi.c | WIFI 모듈을 호출할 때 사용하는 DDI 정의 |
cfgfile.c | profile 파일을 접근하는데 사용하는 API 정의 |
ipc.c | ipc 통신을 하기 위해 필요한 API 정의 |
networkmanager.c | NM 동작의 core API 정의 |
nmdhcp.c | dhcp client 동작시 사용하는 API 정의 |
nmpolicy.c | NM 의 동작 방식을 정의하는 API 정의 |
nmprof.c | profile 을 접근하는데 사용하는 API 정의 |
nmstate.c | NM 의 상태에 따라 호출되는 API 정의 |
ping.c | ping 함수 정의 |
★ 빌드 순서
API 는 NM 과 통신하기 위해서 필요한 부분이다. 따라서 NM 과 통신하고 싶다면, 이들 파일을 함께 빌드해야 한다. 실제로 NM 과 통신하기 위해서 DTV 빌드시, NM API 가 선언된 코드가 함께 빌드된다. 함께 빌드되는 파일은 nm.mk 파일을 보면 알 수 있는데, 이는 epk 전체 빌드시, 각 디렉토리마다 루프를 돌면서 .mk 파일을 실행할 때, 이때 빌드된다.
이름 | 설명 |
nm_ipc.c | NM 과 IPC 통신 시에 사용하는 API 정의 |
nm_processlist.c | NM 프로세스의 유/무 를 판단하는 API 정의 |
nm_osa.c | OS 의존적인 API 정의(Task, Messagequeue, Semaphore) |
nm_api.c | NM 에서 제공하는 API 정의 |
nm_debug.c | Debug 모드에서 사용하는 API 정의 |
NM 은 한번 접속한 기기(유무선 공유기)에 대해서 정보를 파일 형태로 저장한다(nm.rc)
유선 설정은 1개, 무선 설정은 9개까지 저장가능하다. 공장초기화 모드 또는 IN STOP 시에 Profile 은 삭제된다.
파일 형식은 아래와 같다.
[PROF_...] ... [MAIN] ...
이후 Profile 이 생성되면, 아래처럼 추가된다.
[PROF_...] ... [MAIN] ... [PROF_...] // 추가 ...
Profile 에 사용되는 Tag 는 아래와 같다.
Tag | 설명 |
[PROF_e*h3RN#T!] | 유선 Profile |
PROF_SSID명 | 무선 Profile |
Mode | Ethernet(유선), Managed/Adhoc(무선) |
Security | WEP/WPA-PSK/WPA2-PSK(무선), None(유선/무선) |
Encryption | AES/TKIP(무선), None(유선/무선) |
DHCP | 1(Enable), 0(Disable) |
DHCP_DNS | 1(Enable), 0(Disable) |
[MAIN] | 최종으로 성공했던 접속 설정을 가지고 있음 |
USE_ETH | NO(무선), YES(유선) |
PROF1 | 가장 최근에 접속한 Profile |
IP_Address | 사용한 IP 주소 |
IP_Netmask | 넷마스크 주소(IP 수동 설정 시 저장) |
IP_Gateway | 게이트웨이 주소(IP 수동 설정 시 저장) |
DNS1 | 네임서버 주소(DNS 수동 설정 시 저장) |
앞서 설명했듯이 NM 은 별도의 프로세스로 동작한다. 아래로는 커널과 위로는 DTV 프로세스와 서로 통신하며 이벤트 정보를 전달해주는 역할을 한다.
이때 사용하는 방법으로는 netlink(커널), ipc(DTV 프로세스), socket(Dhcp) 이 있다. 각각의 통신 경로마다 주고 받는 정보가 다르며, 실시간으로 발생하는 이벤트에 대해 처리를 해주어야 한다. 또한 NM 은 State machine 구조를 가지는데, 어떤 이벤트가 발생했을 때 그에 맞는 state 로 변경되어 처리하게 된다.
그외에도 주기적으로 NM 프로세스가 죽었는지 여부를 확인하는 Thread, 외부와의 네트워크 연결이 이루어졌는지 확인하는 Thread 등을 통해 네트워크 상태를 체크한다.
실제 DTV 와 NM 에서 각각 동작하는 시퀀스에 대해 살펴보자.
부팅 처음에 네트워크 인터페이스를 초기화 시키고, NM 과 통신할 수 있는 통로(IPC 소켓)를 생성하고, NM 에 IPC 소켓에 연결한다. 또한 이벤트가 발생했을 때, 이를 처리하기 위해 이벤트 목록을 등록하여 해당 이벤트 발생 시에 이에 해당되는 처리 함수를 실행할 수 있도록 callback 함수로 만든다. 이후, NM 프로세스가 정상적으로 동작하는 여부를 Thread 를 사용하여 주기적으로 확인한다.
DTV 와 통신하기 위해서 IPC, 커널과 통신하기 위해 netlink 소켓을 생성한다. Dhcp 서버로 부터 IP 주소를 할당 받기 위해 소켓을 생성한다. 이후 이들로 부터 데이터가 들어오거나 타임아웃이 발생할 때마다 마다 이에대한 처리를 수행한다.
netlink 소켓은 사용자 프로세스와 커널 사이의 통신 수단을 제공한다. netlink 소켓을 거쳐 통신하는 기능은 라우팅 테이블과 ARP 테이블을 포함한다. netlink 소켓은 소켓 API 를 사용해 커널 영역과 사용자 영역 사이에 통신이 가능하게 만드는 효율적인 매커니즘이다. 현재 커널은 핫플러그를 감지하면 netlink 소켓을 거쳐 사용자 영역으로 uevent 를 보낸다.
NM 에서 Netlink 소켓을 통해 라우팅 업데이트 및 ipv4 라우팅 테이블, ip 주소, link parameters 등에 대하여 조정가능하며, 커널 내에 있는 라우팅 테이블의 정보를 얻거나 변경할 수 있다. 또한 네트워크 인터페이스가 create/delete/up/down 되었을 때, 이벤트를 listen 할 수 있다.
NM 에서는 Netlink 소켓으로 들어오는 데이터를 파싱하여 어떤 디바이스에서 어떤 타입의 데이터가 왔는지에 따라 이벤트 핸들러 함수(nm_sm_event)를 호출한다.
상대방과 링크가 활성화되었을 경우, 이벤트가 발생하여 파싱한다. 이때 반환되는 값에 따라 다르게 처리한다.
DTV 와 이벤트를 주고 받기 위해 사용한다.
DTV 에서는 sync/async/event IPC 소켓을 만들어 NM 과 통신한다. DTV 에서 IPC 메시지 패킷을 보낼 때, 사용하는 이벤트 타입 종류는 NM 과 동일하다.
NM 에서는 IPC 소켓으로 부터 데이터가 들어오면, 이를 파싱하여, 이에대한 처리를 한다. 이때 이벤트 핸들러 함수(nm_sm_event)를 호출한다.
DTV 에서는 IPC 데이터를 보낼 때, 특성에 따라 각각 다른 소켓으로 전송한다. 총 3가지를 사용하는 데, 다음과 같다.
DTV 에서 NM 에 이벤트 메세지를 보내고, 그 결과값을 받아야 하는 경우에 사용한다. 서로 간에 동기화가 맞아야 하기 때문에 결과값을 받기 전까지 blocking(2초) 이 걸린다(NM_IPC_ClientBlockRecv).
아래의 함수들이 sync ipc 소켓을 사용한다.
DTV UI 로 부터 호출되어 NM 으로 IPC 메세지를 보내고, 응답이 올때 까지 기다리지 않는다. 이후 다른 작업을 하고, 이에 대한 처리 결과가 이벤트로 UI 에 전달되면 이에 대한 처리를 한다. 아래의 함수들이 async ipc 소켓을 사용한다.
해당 소켓으로 이벤트가 발생했을 때, 이를 UI 로 메세지를 보낸다(NM_EventHandler). 이후 UI 에서는 이를 받아 각 이벤트에 맞는 처리를 하게 된다.
event 소켓은 스레드(_NM_CheckIPCEventThread) 에 의해 1초마다 루프를 돌며 해당 소켓에 데이터가 들어왔는지 확인한다.
유선 또는 무선 연결이후, DHCP 서버로 부터 IP 주소를 할당 받기 위해서는 서버와 몇 번의 통신이 필요하다. 이는 순전히 DHCP 프로토콜의 정의에 따른다.
DTV 의 MAIN_DoPostAddonInitTask() 로 부터 호출되며, 매 2초 주기로, NM 프로세스가 살아있는지 여부를 확인한다. 이는 /proc/ 아래의 해당 PID 디렉토리의 stat 파일을 read 하여 알아낸다.
IPC 이벤트 데이터를 주고 받기 위해 만든 소켓에 데이터가 들어왔는지 여부를 1초마다 확인한다(select).
데이터가 들어왔으면, 이를 버퍼(pBuf)에 복사한다. 이때 데이터를 받을 때(recv)는 blocking 된다. 버퍼에 저장된 데이터를 이벤트 ID 와 함께 UI 로 메세지를 보낸다.
위와 같은 작업을 무한 루프로 돌면서 실행한다.
Description | NM 과 sync, async 한 IPC 메세지를 주고 받기 위해 소켓을 열고 접속을 시도한다. |
Syntax | INT32 API_NM_InitializeModule(void) |
Parameters | None |
Return Value | If the function succeeds, the return value is WIFI_OK. |
If the function fails, the return is WIFI_FAIL. | |
Remarks | DTV 에서 NM 프로세스 실행 후에 이와 통신하기 위해서 가장 먼저 호출되어야 하는 함수이다. |
See Also | None |
'<Pseudo Code>'
WIFI_STATUS_T DDI_WIFI_SetLEDStatus(WIFI_LED_STATUS_T status) { /* Set led status */ Write IOCTL to WIFI with data IF any error THEN RETURN WIFI_FAIL ELSE RETURN WIFI_OK END IF }
'<Example>'
DDI_WIFI_SetLEDStatus(FLASE); // LED OFF DDI_WIFI_SetLEDStatus(TRUE); // LED ON
Description | NM 과 sync, async 한 IPC 메세지를 주고 받기 위해 소켓을 열고 접속을 시도한다. |
Syntax | INT32 API_NM_InitializeModule(void) |
Parameters | None |
Return Value | If the function succeeds, the return value is WIFI_OK. |
If the function fails, the return is WIFI_FAIL. | |
Remarks | DTV 에서 NM 프로세스 실행 후에 이와 통신하기 위해서 가장 먼저 호출되어야 하는 함수이다. |
See Also | None |
'<Pseudo Code>'
WIFI_STATUS_T DDI_WIFI_SetLEDStatus(WIFI_LED_STATUS_T status) { /* Set led status */ Write IOCTL to WIFI with data IF any error THEN RETURN WIFI_FAIL ELSE RETURN WIFI_OK END IF }
'<Example>'
DDI_WIFI_SetLEDStatus(FLASE); // LED OFF DDI_WIFI_SetLEDStatus(TRUE); // LED ON