6 min read

NGAP와 함께 보는 ASN.1 - 1st

NGAP와 함께 보는 ASN.1 - 1st
Photo by Marcel Eberle / Unsplash

NGAP

NGAP (Next Generation Application Protocol)은 5G 네트워크에서 gNB와 AMF 사이의 N2 인터페이스 프로토콜이며 asn.1의 PER에 따라 인코딩하여 주고 받는다. NGAP 표준에 정의된 asn.1 문서는 총 여섯 개이다.

  • NGAP-CommonDataTypes.asn
  • NGAP-Constants.asn
  • NGAP-Containers.asn
  • NGAP-IEs.asn
  • NGAP-PDU-Contents.asn
  • NGAP-PDU-Descriptions.asn

이제부터 수차례에 걸쳐 각 .asn 파일을 하나씩 열어 asn.1 표준을 분석해볼 것이다. NGAP 자체를 분석하는 것이 목적이 아니기 때문에 asn.1 문법 상 중복되는 내용은 생략하고 건너뛸 것이다. 표준문서는 3GPP Rel 16.3의 것을 기준으로 한다.

먼저 NGAP-CommonDataTypes.asn 파일부터 분석한다.

Object Identifier

파일은 아래 내용으로 시작한다.

NGAP-CommonDataTypes {
itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
ngran-Access (22) modules (3) ngap (1) version1 (1) ngap-CommonDataTypes (3) }

NGAP-CommonDataTypes은 해당 파일에 ASN.1으로 정의된 모듈의 식별자다. 모듈 식별자는 파일명과 똑같게 정한다. asn.1로 작성한 파일이 여러 개 있고 서로 다른 파일을 참조할 경우에는 모듈 식별자를 갖고 참조할 파일을 결정하기 때문이다.

모듈명 다음의 {...}는 해당 모듈의 OID(Object Identifier)를 정의한 부분이다. OID는 전 세계적으로 고유한 식별자로 계층적 구조를 가진다. 위의 내용을 분석하면 다음과 같다.

  1. itu-t (0): ITU-T 기관
  2. identified-organization (4)
  3. etsi (0): ETSI 유럽 표준화 기구
  4. mobileDomain (0)
  5. ngran-Access (22): NG-RAN 무선 접속망
  6. modules (3)
  7. ngap (1): Next Generation Application Protocol (NGAP)
  8. version1 (1): 버전 정보
  9. ngap-CommonDataTypes (3)

제일 처음의 itu-t (0)은 ITU-T에서 결정한 값으로, X.660 표준에 정의되어 있다. 참고로 X.660은 바로 이 OID에 대한 표준으로, ITU-T에서 관리하고 있다. 그 뒤로는 ETSI, 3GPP 등 하위 단체 순으로 다음 OID 값을 결정한다. 이런 계층적 방식으로 해당 asn.1 모듈을 전 세계적으로 고유하게 식별될 수 있다.

asn.1 모듈의 몸통

그 다음 내용을 보면 나머지 내용은 대부분 BEGINEND 사이에 있음을 알 수 있다.

DEFINITIONS AUTOMATIC TAGS ::=

BEGIN
  ...
END

이 부분은 asn.1 모듈 정의의 시작과 끝을 나타낸다. 우선 첫 줄은 다음과 같다.

  • DEFINITIONS: asn.1 모듈 정의의 시작
  • AUTOMATIC TAGS: 모듈에서 사용되는 모든 태그가 자동으로 할당됨을 나타낸다. 이 경우 모듈 내의 각 구성 요소에 대해 명시적으로 태그를 정의하는 대신 context specific 태그를 자동으로 붙여주기 때문에 모듈 내의 타입 정의가 훨씬 더 간결해진다.
  • ::=: asn.1에서의 할당 연산자로, 왼쪽에 있는 식별자에 오른쪽에 있는 값을 할당한다.
  • BEGIN, END: 모듈 정의의 시작과 끝을 나타낸다. 이 사이의 내용에 모듈에서의 타입과 값 정의가 포함된다.

타입의 정의

다음은 Criticality라는 이름의 새로운 타입을 정의한다.

Criticality ::= ENUMERATED { reject, ignore, notify }
  • Criticality: 정의하고자 하는 새로운 타입의 이름
  • ENUMERATED: enumerated(열거형) 타입. 명시된 여러 개의 가능한 값 중 하나를 가질 수 있다.
  • { reject, ignore, notify }: Criticality 타입은 여기에 나열된 값 중 하나를 가질 수 있다.

ENUMERATED에 열거된 값들은 나열된 순서대로 다음과 같이 0부터 시작하는 정수 값에 매핑된다.

  • reject: 0
  • ignore: 1
  • notify: 2

BER과 DER의 경우 정수 값은 1바이트씩 인코딩된다. 물론 태그와 길이까지 추가된 완전한 TLV 포맷으로는 더 늘어난다. PER의 경우 정수 값은 최소 길이의 비트로 표현된다. 여기서는 총 3개의 값을 가지므로 다음과 같이 2비트로 인코딩된다.

  • reject: 00
  • ignore: 01
  • notify: 10

다음은 PrivateIE-ID라는 이름의 CHOICE 타입을 정의한다.

PrivateIE-ID ::= CHOICE {
  local   INTEGER (0..65535),
  global  OBJECT IDENTIFIER
}

CHOICE 타입은 여러 개의 타입 중 하나를 선택하여 사용할 수 있는 데이터 타입이다. 이 경우 PrivateIE-IDlocal이라는 이름의 INTEGER 타입 또는 global이라는 이름의 OBJECT IDENTIFIER 타입 중 하나를 선택할 수 있다.

  • PrivateIE-ID: 정의하고자 하는 새로운 타입의 이름
  • CHOICE: 여러 개의 타입 중 하나를 선택하여 사용할 수 있는 데이터 타입
  • local INTEGER (0..65535): 0에서 65535까지의 범위를 갖는 local이라는 이름의 INTEGER 타입
  • global OBJECT IDENTIFIER: global이라는 이름의 OBJECT IDENTIFIER 타입

OBJECT IDENTIFIER는 앞서 설명한 전 세계적으로 고유한 OID를 의미한다. OID를 인코딩하는 방법에 대해서는 나중에 설명하기로 한다.

PER로 인코딩할 때, CHOICE 타입의 경우 안에 정의된 여러 타입 중 어떤 것을 쓰고 있는지 가리키는 선택 비트가 먼저 추가된다. 위의 경우 2개 중에서 선택하는 것이므로 1비트만 사용된다.

  • local: 0
  • global: 1

local인 경우 65535까지의 값을 갖는 정수를 사용하므로 값은 16비트로 할당된다. 예를 들어 0xffff 정수를 사용한 경우 PrivateIE-ID는 다음과 같이 인코딩된다.

- `local` select bit: `0`
- padding bits:       ` 000 0000`
- integer (16bits):   `         1111 1111 1111 1111`

다음은 INTEGER 타입으로 정의되는 ProcedureCode이다. 0에서 255 사이의 값을 가지기 때문에 8비트 정수로 인코딩될 것이다.

ProcedureCode ::= INTEGER (0..255)

PER의 경우, 정수 값은 그대로 이진수 형태로 인코딩되므로 값이 42인 경우 이진수로 0010 1010 (0x2a)로 인코딩된다.

만약 DER이라면, tag와 길이까지 합쳐 다음과 같이 인코딩된다.

  1. tag: INTEGER 타입은 범용 클래스 태그 2를 가진다. (0x02)
  2. length: 값이 8비트 이내에 표현되므로 길이 값은 1이다. (0x01)
  3. value: 정수 값 42는 16진수로 0x2a가 된다.

따라서 인코딩된 결과는 02 01 2a가 된다.

여기까지 NGAP-CommonDataTypes.asn의 내용을 살펴봤다. 담고 있는 내용도 제일 적고 구조도 간단하기 때문에 처음에 asn.1에 대해 설명하기가 쉬웠다. 점점 크기도 커지고 구조가 복잡해지는 순으로 .asn 파일을 골라서 설명을 할 것이다.

— END OF POST.