DTV 에서 사용하는 모든 네트워크 상태를 관장하는 NM(=Networkmanger) 에 대해서 설명한다.

About This Document

Version Date Comment Author
1.0 2011-1-31 최초 작성 연구7실 AP 그룹 김우종 주임연구원

본 문서는 모든 네트워크 상황에 대해 관장하는 Middleware 인 NM 의 모든 것에 대해서 다룬다. 이 문서를 통해 DTV 에서의 네트워크 동작과 이를 이용한 서비스들(ex: Broadband)의 동작을 좀더 쉽게 이해할 수 있고 나아가서는 이를 디버깅 및 기능 개선을 하는데 소요되는 시간을 줄일 수 있을 것이라 기대한다.

소스코드와 API 함수 표기는 굴림 글꼴로 표시한다.

내용 중 알아두면 편리한 참고 사항과 반드시 알아야 하는 중요 사항을 다음과 같이 표시한다.

<Note> 내용 중 알아두면 편리한 각종 참고 사항
<Caution> 내용 중 반드시 알아야 하는 중요한 사항

본 문서는 다음과 같은 약어를 사용한다.

Acronym Description
NM Networkmanager

Overview

NM 은 DTV 에서 유/무선 네트워크의 설정, 접속등을 관리한다. 랜선이 꼽히거나, WiFi 로 AP 에 접속할 때 모두 NM 의 동작을 거친다. 위로는 UI 와 아래로는 Wired/Wireless Driver 와 정보를 주고 받는다. 추가로 dhcp client 기능도 가진다.

NM 은 독립적인 프로세스로 동작한다.

  1. 사용하려는 Network 인터페이스에 대해 외부와 통신이 가능하도록 설정 가능함(ethernet/wi-fi)
  2. profile 을 이용하여 한번 접속했던 기기에 대해 자동으로 접속이 가능함

코드는 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개의 오브젝트 파일이 생성된다.

  1. 'Networkmanager.basic' : Netcard 코드가 제외되어 빌드한 파일
  2. 'Networkdmanager.netcard' : Netcard 코드가 포함되어 빌드한 파일

앞서 말했듯이 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 함수 정의

★ 빌드 순서

  1. basic, netcard 각각 해당하는 파일을 빌드하여, 라이브러리를 생성한다(libnm_basic.a/libnm_netcard.a).
  2. WIFI Driver 의 압축을 풀고, WPS 라이브러리를 생성한다. 또한 lgm_enr_api.c 를 빌드한다.
  3. 해당 파일(위의 표 참조)을 빌드한다.
  4. 앞서 빌드하여 생성된 것을 링킹하여 최종 바이너리 파일(Networkmanager.basic/Networkmanager.netcard)을 생성한다.

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 를 사용하여 주기적으로 확인한다.

  1. Wi-Fi drvier module load 및 eth0, lo 인터페이스 활성화 함 <MAIN_DoPostAddonInitTask>
  2. NM 을 실행한다 : SCHED_RR, Priority(40) <MAIN_DoPostAddonInitTask>
  3. IPC 통신(sync/async)을 위한 소켓을 생성(3490)하고 연결한다(connect) <API_NM_InitializeModule>
  4. 처리할 이벤트들에 대해서 callback 함수에 등록한다. 이벤트를 IPC 로 처리하기 위한 소켓을 생성한다(3490) 이후 등록된 이벤트가 발생하면, UI 로 해당 이벤트를 보낸다 <API_NM_RegisterEventAll>
  5. CheckNM 쓰레드를 생성한다 : NM 프로세스가 없거나, 5번 이상 API 호출이 제대로 동작하지 않을 경우, NM 을 새로 시작한다. 처음 5초 기다린 이후 동작하고, 이후 2초마다 주기적으로 NM 프로세스를 체크한다. <NM_CHECK_ALIVE_Task>

DTV 와 통신하기 위해서 IPC, 커널과 통신하기 위해 netlink 소켓을 생성한다. Dhcp 서버로 부터 IP 주소를 할당 받기 위해 소켓을 생성한다. 이후 이들로 부터 데이터가 들어오거나 타임아웃이 발생할 때마다 마다 이에대한 처리를 수행한다.

  1. signal(interrupt, quit) 에 대해 무시함 <main>
  2. default policy 를 읽음 <_nm_setDefaultPolocy>
  3. 외부 & 내부에서 사용할 구조체 초기화함. 커널에 발생한 이벤트를 받기 위해 netlink 소켓 생성함(open & bind) <_nm_init>
  4. DTV 와 통신할 때 사용할 IPC 소켓을 생성함(open & bind) <main>
  5. ethernet 과 wi-fi 인터페이스에 대한 정보(if_name, mac addr, index)를 얻는다. 이때는 ioctl command 를 사용한다 <nm_get_eth_ifname, nm_get_wl_ifname>
  6. 현재 연결되어 있는 인터페이스를 체크한다. 연결된 인터페이스에 대한 정보를 current 구조체에 저장한다. 만일 둘다 꼽혀 있다면, profile 을 읽어서 결정한다. 참고로nm_sm_event 함수는 이벤트가 발생할 때마다 실행되며, state 와 발생한 event 에 따라 해당 처리루틴이 수행된다 <nm_sm_event>
  7. netlink, IPC, Dhcp 소켓에서 들어오는 데이터를 확인하기 위해 파일 디스크립터(FD)를 초기화한다. 또한 각각 state machine(3초), dhcp(5초), scan(2초) 타임아웃이 발생했다면, 시간을 초기화한다. netlink, IPC, Dhcp 소켓으로 부터 데이터가 들어오기까지, 또는 타임아웃이 발생하기 전까지 select 함수에 의해 Lock 에 걸려있다. 어떤 데이터가 들어왔다면, 이를 파싱하여 해당 루틴을 실행한다. 마찬가지로 타임아웃이 발생했다면, 이에 대한 처리를 수행한다. 참고로 이 루틴은 NM 이 죽기전까지 루프를 돌면서 수행한다 <_nm_init_environment>

netlink 소켓은 사용자 프로세스와 커널 사이의 통신 수단을 제공한다. netlink 소켓을 거쳐 통신하는 기능은 라우팅 테이블과 ARP 테이블을 포함한다. netlink 소켓은 소켓 API 를 사용해 커널 영역과 사용자 영역 사이에 통신이 가능하게 만드는 효율적인 매커니즘이다. 현재 커널은 핫플러그를 감지하면 netlink 소켓을 거쳐 사용자 영역으로 uevent 를 보낸다.

NM 에서 Netlink 소켓을 통해 라우팅 업데이트 및 ipv4 라우팅 테이블, ip 주소, link parameters 등에 대하여 조정가능하며, 커널 내에 있는 라우팅 테이블의 정보를 얻거나 변경할 수 있다. 또한 네트워크 인터페이스가 create/delete/up/down 되었을 때, 이벤트를 listen 할 수 있다.

NM 에서는 Netlink 소켓으로 들어오는 데이터를 파싱하여 어떤 디바이스에서 어떤 타입의 데이터가 왔는지에 따라 이벤트 핸들러 함수(nm_sm_event)를 호출한다.
상대방과 링크가 활성화되었을 경우, 이벤트가 발생하여 파싱한다. 이때 반환되는 값에 따라 다르게 처리한다.

  1. 인터페이스 이름이 반환된 경우 : 인터페이스를 파싱하여 해당 인터페이스 정보를 얻는다.
  2. 인터페이스 상태가 반환된 경우 : 상태를 알지 못하는 상태이거나, up 또는 down 되었을 때(예를들어 Ethernet 케이블이 빠졌거나 꼽혔을 때), 이에 대한 처리를 한다.

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 소켓을 사용한다.

  1. API_NM_GetCurrentNetworkStatus
  2. API_NM_GetAPSearchResult
  3. API_NM_GetCurrentNetworkManagerStatus
  4. API_NM_CheckNetworkConnection

DTV UI 로 부터 호출되어 NM 으로 IPC 메세지를 보내고, 응답이 올때 까지 기다리지 않는다. 이후 다른 작업을 하고, 이에 대한 처리 결과가 이벤트로 UI 에 전달되면 이에 대한 처리를 한다. 아래의 함수들이 async ipc 소켓을 사용한다.

  1. API_NM_ChangeIface
  2. API_NM_Check_SDP_Auth
  3. API_NM_StartAPSearch
  4. API_NM_CancelAPSearch
  5. API_NM_ConnectWithWPSMode
  6. API_NM_CancelConnectWithWPSMode
  7. API_NM_ConnectWithSelectedAP
  8. API_NM_CancelConnect
  9. API_NM_SetIP
  10. API_NM_SetWiFiCountryCode
  11. API_NM_FactoryReset
  12. NM_SetDebugMode

해당 소켓으로 이벤트가 발생했을 때, 이를 UI 로 메세지를 보낸다(NM_EventHandler). 이후 UI 에서는 이를 받아 각 이벤트에 맞는 처리를 하게 된다.
event 소켓은 스레드(_NM_CheckIPCEventThread) 에 의해 1초마다 루프를 돌며 해당 소켓에 데이터가 들어왔는지 확인한다.

유선 또는 무선 연결이후, DHCP 서버로 부터 IP 주소를 할당 받기 위해서는 서버와 몇 번의 통신이 필요하다. 이는 순전히 DHCP 프로토콜의 정의에 따른다.

DTV 의 MAIN_DoPostAddonInitTask() 로 부터 호출되며, 매 2초 주기로, NM 프로세스가 살아있는지 여부를 확인한다. 이는 /proc/ 아래의 해당 PID 디렉토리의 stat 파일을 read 하여 알아낸다.

  1. 만일 해당 PID 가 없다면, NM 을 재 실행한다.
  2. NM API 호출 도중 에러가 5번이상 발생하면(_apiFailCount), DTV 쪽에서의 IPC 연결을 모두 close 시킨다API_NM_FinalizeModule).

IPC 이벤트 데이터를 주고 받기 위해 만든 소켓에 데이터가 들어왔는지 여부를 1초마다 확인한다(select).
데이터가 들어왔으면, 이를 버퍼(pBuf)에 복사한다. 이때 데이터를 받을 때(recv)는 blocking 된다. 버퍼에 저장된 데이터를 이벤트 ID 와 함께 UI 로 메세지를 보낸다.
위와 같은 작업을 무한 루프로 돌면서 실행한다.

API Reference Guide

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
  • computer/lg/nm_api_핵심가이드.txt
  • Last modified: 3 years ago
  • by likewind