들어가기전..

 

본 내용은 MPTCP와 Netlink에 관한 지식이 있으면 조금 더 쉽게 이해할 수 있을 것이다.

 


MPTCP Netlink PM 이란?

 

MPTCP의 Path Manager는 표준 Socket API를 App(유저영역)으로 노출시킨다.

이것은 네트워크의 Multipath 특성을 모르는 App에게는 주요한 기능이다.

 

그러나 특정 분야에서 성능을 높일 수 있는 App에게는 제한 사항이 된다.

이러한 문제점을 해결하기 위해 MPTCP Netlink PM(Path Manager)이 도입되었다.

 

이 PM은 Kernel에 구성되어서 "Events""Commands"를 User 영역 App에 드러낸다.

그리고 MPTCP의 Subflow 생성 및 제거 그리고 재전송 응답과 같은 주요기능들의 컨트롤을 App에게 위임한다.

 

 

위 그림과 같이 MPTCP Netlink PM은 Subflow 제어와 관련된 부분을 모두 User 영역으로 위임하였다.

그리고 Subflow Controller(User App)는 PM Library를 통해 Linux Kernel 내에 존재하는 Netlink PM과

Netlink Message로 상호작용한다.

 

MPTCP Netlink Path Manager를 좀 더 자세히 알고싶다면 아래 링크를 참조하길 바란다.

https://dl.acm.org/doi/abs/10.1145/2716281.2836113

 

MPTCP Netlink API Request & Response Message

 

MPTCP Netlink PM은 multipath-tcp.org에서 제공되는 MPTCP v0.95 이상 버전에서 API 형태로 제공되고 있다.

이 API는 Generic Netlink Message를 통해 데이터를 주고(Request) 받을(Response) 수 있다.

Generic Netlink는 기존 Netlink와 크게 다를 것은 없다.

 

Generic Netlink는 커널내에 분산되어 존재하는 Netlink를 Generic Bus에 묶어서 제어하기 위해 사용하는 것이다.

 

 

Generic Netlink에 대한 구조는 위 그림과 같다.

 

이제 Generic Netlink의 Message Format에 대해 알아보자.

 

 

Generic Netlink Message의 Header는 다음 위 그림과 같다.

Total Length 필드부터 Process ID 필드까지는 기존 Netlink Message의 Header 영역이고

여기에 Command(8bit), Version(8bit), Reserved(16bit)까지 포함시키면 Generic Netlink Message의 Header가 된다.

가장 마지막에 존재하는 Netlink Message Attributes 영역 부터는 Header가 아닌 Payload 부분이다.

Payload 부분은 Header를 설명한 뒤에 설명한다.

 

Generic Netlink Header에서 각 필드들의 역할은 다음과 같다.

  • Total Length
    : 헤더크기를 포함한 메시지의 전체 길이이다.
  • Type
    : Generic Netlink의 id를 나타낸다. (Ex. MPTCP Netlink PM의 ID)
  • Flags
    : 메시지의 역할을 나타낸다. (Ex. Request, Error 등)
  • Sequence Number
    : 메시지의 시퀀스 번호이다.
  • Process ID
    : 메시지를 전송하는 Process ID를 나타낸다.
  • Command
    : Generic Netlink 메시지 타입을 나타낸다. (Ex. Netlink PM의 Event인지 Command인지)
  • Version
    : Generic Netlink 모듈의 버전을 나타낸다.
  • Reserved
    : Padding 역할로 16bit가 모두 0으로 채워진다.

 

이제 Generic Netlink Message의 Payload 영역을 살펴본다.

 

 

Payload 영역은 Generic Netlink Message의 Header 다음에 부착되며 nla(Netlink Attribute)로 표현된다.

또한, 이 Attribute는 Request, Response 메시지에 따라 한개로 구성될 수도 있고 여러개로 구성이 될 수도 있다.

 

하나의 Netlink Attributes의 필드들은 다음과 같은 역할을 한다. 

  • nla_length
    : 하나의 Attribute의 전체 길이
  • nla_type
    : 하나의 Attirubte의 타입 (data가 무엇을 의미하는지를 나타낸다.)
  • data
    : 하나의 Attribute data

 

MPTCP Netlink API 문서

 

multipath-tcp.org에서 제공하는 MPTCP(v0.95) Netlink PM에 대한 API 문서는 아래 링크를 통해 확인할 수 있다.

https://github.com/multipath-tcp/mptcp/blob/mptcp_v0.95/include/uapi/linux/mptcp.h

 

API 문서에서 살펴보면 MPTCP(v0.95)의 Netlink PM은 다음과 같은 Commands와 Events를 제공한다.

각 Commands와 Events는 아래에 설명한다.

 

  • Commands
    • MPTCP_CMD_ANNOUNCE
      : 연결된 상대에게 자신의 사용가능한 IP 주소를 전송 (ADD_ADDR)
    • MPTCP_CMD_REMOVE
      : 연결된 상대에게 저장된 자신의 IP 주소를 삭제 (REM_ADDR)
    • MPTCP_CMD_SUB_CREATE
      : 연결된 상대에게 새로운 Subflow 연결 요청 (MP_JOIN)
      : *새로운 Subflow를 연결하기 전에 ADD_ADDR 교환이 먼저 이루어져 있어야 한다.
    • MPTCP_CMD_SUB_DESTORY
      : 연결된 Subflow를 닫기
    • MPTCP_CMD_SUB_PRIORITY
      : Subflow 간의 우선순위 변경 (MP_PRIO)
    • MPTCP_CMD_SET_FILTER
      : 특정 Event만 받을 수 있는 Filter 설정
    • MPTCP_CMD_EXIST
      : MPTCP Connection의 Token 값이 현재 사용 중인 값인지 중복확인
  • Events
    • MPTCP_EVENT_CREATED
      : 새로운 MPTCP Connection이 생성되었을 때 수신되는 Event
      : *이 Event가 수신되었을 때 MPTCP_CMD_ANNOUNCE를 시행하기 가장 적합한 때이다.
    • MPTCP_EVENT_ESTABLISHED
      : 새로운 MPTCP Connection이 Established 상태가 되었을 때 수신되는 Event
      : *이 Event가 수신되었을 때 MPTCP_CMD_SUB_CREATE를 시행하기 가장 적합한 때이다.
      : *또한, 반드시 MPTCP_CMD_ANNOUNCE를 통해 새로운 연결을 수행할 Subflow의 IP가 사전교환 되어 있어야한다.
    • MPTCP_EVENT_CLOSED
      : MPTCP Connection이 종료되었을 때 수신되는 Event
    • MPTCP_EVENT_ANNOUNCED
      : 상대측이 MPTCP_CMD_ANNOUNCE를 시행시켰을 때 발생하는 Event이다.
      : 즉, 상대측에서 MPTCP의 ADD_ADDR 패킷을 전송하였을 때 발생되는 Event
    • MPTCP_EVENT_REMOVED
      : 상대측이 MPTCP_CMD_REMOVE를 시행시켰을 때 발생하는 Event이다.
      : 즉, 상대측에서 MPTCP의 REM_ADDR 패킷을 전송하였을 때 발생되는 Event
    • MPTCP_EVENT_SUB_ESTABLISHED
      : 새로운 Subflow의 Connection이 Established 상태가 되었을 때 수신되는 Event
    • MPTCP_EVENT_SUB_CLOSED
      : 특정 Subflow가 닫혔을 때 수신되는 Event
    • MPTCP_EVENT_SUB_PRIORITY
      : 상대측이 MPTCP_CMD_SUB_PRIORITY를 시행시켰을 때 발생하는 Event이다.
      : 즉, 상대측에서 MPTCP의 MP_PRIO 패킷을 전송하였을 때 발생되는 Event

 

위와 같은 Command와 Event는 Generic Netlink Message의 Header 영역에서 Command(8bit) 필드에 담기게 된다.

또한 Message의 Payload에 부착되는 Attribute의 Type(nla_type)에 대한 설명이 추가로 되어있다.

Type에 대한 설명은 아래에 되어있다.

 

 

  • Attribute
    • MPTCP_ATTR_TOKEN
      : MPTCP 초기 연결(MP_CAPABLE)과정 중 생성된 Local Token 값을 나타낸다.

      : Token은 32bit로 표현된다.
    • MPTCP_ATTR_FAMILY
      : MPTCP의 IP 버전을 나타낸다. (IPv4 or IPv6)

      : Family는 16bit로 표현된다.
    • MPTCP_ATTR_LOC_ID
      : MPTCP Connection 상에서 Subflow의 Local(Source) IP의 고유한 ID를 나타낸다.

      : loc_id는 8bit로 표현된다.
    • MPTCP_ATTR_REM_ID
      : MPTCP Connection 상에서 Subflow의 Remote(Destination) IP의 고유한 ID를 나타낸다.

      : rem_id는 8bit로 표현된다.
    • MPTCP_ATTR_SADDR4
      : Subflow의 Local IPv4 Address를 나타낸다.

      : saddr4는 32bit로 표현된다.
    • MPTCP_ATTR_SADDR6
      : Subflow의 Local IPv6 Address를 나타낸다.

      : saddr6는 struct in6_addr로 표현된다.
    • MPTCP_ATTR_DADDR4
      : Subflow의 Remote IPv4 Address를 나타낸다.

      : daddr4는 32bit로 표현된다.
    • MPTCP_ATTR_DADDR6
      : Subflow의 Remote IPv6 Address를 나타낸다.

      : daddr6는 struct in6_addr로 표현된다.
    • MPTCP_ATTR_SPORT
      : Subflow의 Local Port 번호를 나타낸다.

      : sport는 16bit로 표현된다.
    • MPTCP_ATTR_DPORT
      : Subflow의 Remote Port 번호를 나타낸다.

      : dport는 16bit로 표현된다.
    • MPTCP_ATTR_BACKUP
      : Subflow의 Priority 상태를 나타낸다.

      : Backup 값이 0일 땐 Primary 이며, 1일 땐 Backup이다.
      : backup은 8bit로 표현된다.
    • MPTCP_ATTR_ERROR
    • MPTCP_ATTR_FLAGS
    • MPTCP_ATTR_TIMEOUT
    • MPTCP_ATTR_IF_IDX

 

MPTCP Netlink API Message Example

 

Header, Payload 필드와 API에 대한 설명만 해두면 이해하기 힘들 수 있으니

한가지 예로, MPTCP Netlink PM에서 User App으로 보내는 Event 메시지를 하나 살펴보도록 하자.

 

64 00 00 00 16 00 00 00 00 00 00 00 00 00 00 00 01 01 00 00 08 00 01 00 0A FF 42 39 06 00 02 00 02 00 00 00 05 00 03 00 00 00 00 00 05 00 04 00 00 00 00 00 08 00 05 00 C0 A8 01 09 08 00 07 00 C0 A8 01 0B 06 00 09 00 9C E9 00 00 06 00 0A 00 0F 27 00 00 05 00 0B 00 00 00 00 00 08 00 0F 00 00 00 00 00

 

위 Hex(16진수) 데이터는 Netlink PM에서 App으로 보내는 MPTCP_EVENT_CREATED라는 Event이다.

Hex 데이터를 앞서 살펴본 Header와 Payload 필드에 맞추어 보면 아래 그림과 같은 형태가 된다.

 

 

위 20Byte는 Generic Netlink Message의 Header 영역이고

나머지 아래 80Byte는 Message의 Payload 영역이다.

 

먼저 Header를 해석해보자.

  • Header
    • Total Length = 0x64 00 00 00
      : 0x64를 10진수로 변경하면 100이라는 수가 나온다.
      : 이 Message의 전체 크기는 100Byte라는 것을 알 수 있다.
    • Type = 0x16 00
      : 0x16를 10진수로 변경하면 22라는 수가 나온다.

      : 커널내에 존재하는 Netlink PM의 ID가 22인 것을 알 수 있다. 
    • Flags = 0x00 00
      : Nothing
    • Sequence Number = 0x00 00 00 00
      : Nothing
    • Process ID = 0x00 00 00 00
      : PID가 0임으로 커널로부터 수신된 메시지인 것을 알 수 있다.
    • Command = 0x01
      : 위 API문서에서도 볼 수 있듯이 1은 MPTCP_EVENT_CREATED인 것을 알 수 있다.
    • Version = 0x01
      : Netlink PM의 버전이 1인 것을 알 수 있다.
    • Reserved = 0x00 00
      : Padding

 

이제 Payload를 해석해보자.

Payload 안에 Attribute가 많음으로 주요한 Attribute들만 살펴보도록 한다. 

 

  • Payload
    • Attribute 1
      • nla_length = 0x08 00
        : 한개의 Attribute 길이를 나타내는 필드이다.

        : 0x08로 8Byte를 나타내는 것을 알 수 있다.
      • nla_type = 0x01 00
        : 한개의 Attribute의 타입을 나타내는 필드이다.

        : 0x01로 1을 나타내며, API 문서를 살펴보면 Attribute type 1번은 MPTCP_ATTR_TOKEN을 나타낸다.
        : 즉, 이 Attribute의 Data는 MPTCP의 Token 값을 나타내는 것이다.
      • data = 0x0A FF 42 39
        : Token 값
    • Attribute 2
      • nla_length = 0x06 00
        : 0x06으로 길이는 6Byte를 나타낸다.

        : 하지만 이 Attribute의 길이는 8Byte로 나타나는 것을 확인할 수 있다.
        : Netlink Attribute는 4Byte단위로 끊기기 때문에 총 길이는 6Byte가 아닌 8Byte인 것이다.
        : 그렇지만 실제 Data는 6Byte이고 나머지 2Byte는 Padding으로 아무런 의미가 없는 Data가 된다.
      • nla_type = 0x02 00
        : 0x02로 2를 나타내며, MPTCP_ATTR_FAMILY를 나타낸다.

        : 즉, 이 Attribute의 Data는 IPv4 인지 IPv6인지를 나타낸다.
      • data = 0x02 00 00 00
        : 0x02로 2를 나타내며, IPv4 Family를 나타낸다. (sys/socket.h 참조) 
    • Attribute 3
      • nla_length = 0x05 00
        : 0x05로 길이는 5Byte를 나타낸다.
      • nla_type = 0x03 00
        : 0x03으로 3을 나타내며, MPTCP_ATTR_LOC_ID를 나타낸다.

        : 즉, 이 Attribute의 Data는 Subflow Local IP의 ID를 나타낸다. 
      • data = 0x00 00 00 00
        : 가장 초기에는 0으로 설정되며, Local 측에서 ADD_ADDR(MPTCP_CMD_ANNOUNCE)을 통해 변경가능 하다.
    • Attribute 4
      • nla_length = 0x05 00
        : 0x05로 길이는 5Byte를 나타낸다.
      • nla_type = 0x04 00
        : 0x04로 4를 나타내며, MPTCP_ATTR_REM_ID를 나타낸다.

        : 즉, 이 Attribute의 Data는 Subflow Remote IP의 ID를 나타낸다.
      • data = 0x00 00 00 00
        : 가장 초기에는 0으로 설정되며, Remote측에서 ADD_ADDR을 통해 변경가능 하다.
    • Attribute 5
      • nla_length = 0x08 00
        : 0x08로 길이는 8Byte를 나타낸다.
      • nla_type = 0x05 00
        : 0x05로 5를 나타내며, MPTCP_ATTR_SADDR4를 나타낸다.

        : 즉, 이 Attribute의 Data는 Subflow Local IP 값을 나타낸다.
      • data = 0xC0 A8 01 09
        : 각 옥텟을 10진수로 변환하면 192.168.1.9이 된다.

        : 즉, Created된 Subflow의 Local IP를 나타낸다. 
    • Attribute 6
      • nla_length = 0x08 00
        : 0x08로 길이는 8Byte를 나타낸다.
      • nla_type = 0x07 00
        : 0x07로 7을 나타내며, MPTCP_ATTR_DADDR4를 나타낸다.

        : 즉, 이 Attribute의 Data는 Subflow Remote IP 값을 나타낸다.
      • data = 0xC0 A8 01 0B
        : Data의 각 옥텟을 10진수로 변환하면 192.168.1.11이 된다.

        : 즉, Created된 Subflow의 Remote IP를 나타낸다.
    • Attribute 7
      • nla_length =0x06 00
        : 0x06으로 길이는 6Byte를 나타낸다.
      • nla_type = 0x09 00
        : 0x09로 9를 나타내며, MPTCP_ATTR_SPORT를 나타낸다.

        : 즉, 이 Attribute의 Data는 Subflow Local Port 값을 나타낸다.
      • data = 0x9C E9 00 00
        : 앞의 2Byte Data를 10진수로 변환하면 40169가 된다.

        : 즉, Created된 Subflow의 Local Port를 나타낸다.
    • Attribute 8
      • nla_length = 0x06 00
        : 0x06으로 길이는 6Byte를 나타낸다.
      • nla_type = 0x0A 00
        : 0x0A로 10을 나타내며, MPTCP_ATTR_DPORT를 나타낸다.

        : 즉, 이 Attribute의 Data는 Subflow Remote Port 값을 나타낸다. 
      • data = 0x27 0F 00 00
        : 앞의 2Byte Data를 10진수로 변환하면 9999가 된다.

        : 즉, Created된 Subflow의 Remote Port를 나타낸다.
    • Attribute 9
    • Attribute 10

 

지금까지 Generic Netlink Message의 Header와 Payload의 Format을 살펴보았으며,
또한, 실제 Data를 어떻게 해석하면 되는지 예제도 진행해보았다.

실제로 Netlink PM을 사용하는 예제 코드도 아래에 두었으니 살펴보며 이해하길 바란다.

 

MPTCP Netlink API 이슈사항

 

만약, Netlink PM API를 사용한다면 아래의 이슈사항을 살펴볼 필요가 있다.

 

위의 이슈사항은 다음과 같다.
*Packet Scheduler를 RR(Round Robin)으로 설정한 경우 MP_PRIO(MPTCP_CMD_SUB_PRIORITY)가 올바르게 동작하지 않은 문제가 존재한다.

 

답변으로는 RR은 MP_PRIO를 지원하지 않는 Packet Scheduler라고 한다.
해결방안으로는 당연히 RR이 아닌 다른 MPTCP의 Packet Scheduler를 사용하면 된다...!

 

MPTCP Netlink API Example Code

 

아래의 github 링크는 Netlink PM API를 사용하여 2개의 Subflow의 우선순위를 Toggle 해주는 예제이다.
테스트 환경과 사용한 라이브러리 그리고 데모영상도 작성해놓았으니 참고하길 바란다.
https://github.com/pak-ji/mptcp-netlink-api-example

 

아직 MPTCP를 Socket으로 등록하는 것이 미숙하다면 아래의 github 링크를 참조하길 바란다.
이것은 간단하게 MPTCP Socket을 사용하는 방법에 대해 정리해 놓은 것이다.
https://github.com/pak-ji/mptcp-socket-example

 


Ref..

'Linux > MPTCP' 카테고리의 다른 글

MPTCP OFO 패킷 큐 사이즈 측정 (in Linux kernel)  (0) 2022.01.11
MPTCP 설치 for Linux (Debian, RaspberryPi)  (0) 2021.12.07
2. MPTCP 패킷  (0) 2021.07.11
1. MPTCP 개념  (0) 2021.07.09
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기