Documentation/driver-api/connector.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API / Connector

Kernel Connector

Netlink 기반 Kernel Connector의 콜백, 메시지 헤더, seq/ack 프로토콜, 신뢰성과 사용자 공간 그룹 구독을 설명합니다.

Source pathDocumentation/driver-api/connector.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

connector.rst:1-157

Netlink 기반 Kernel Connector의 콜백, 메시지 헤더, seq/ack 프로토콜, 신뢰성과 사용자 공간 그룹 구독을 설명합니다. 영어 원문 전체와 한국어 전문 번역을 함께 제공하며, directive, 함수 시그니처, C 구조체, 심볼, 수치, 소스 경로와 원문 줄 좌표를 보존합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ================
4 Kernel Connector
5 ================
6
7 Kernel connector - new netlink based userspace <-> kernel space easy
8 to use communication module.
9
10 The Connector driver makes it easy to connect various agents using a
11 netlink based network. One must register a callback and an identifier.
12 When the driver receives a special netlink message with the appropriate
13 identifier, the appropriate callback will be called.
14
15 From the userspace point of view it's quite straightforward:
16
17 - socket();
18 - bind();
19 - send();
20 - recv();
21
22 But if kernelspace wants to use the full power of such connections, the
23 driver writer must create special sockets, must know about struct sk_buff
24 handling, etc... The Connector driver allows any kernelspace agents to use
25 netlink based networking for inter-process communication in a significantly
26 easier way::
27
28 int cn_add_callback(const struct cb_id *id, char *name, void (*callback) (struct cn_msg *, struct netlink_skb_parms *));
29 void cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 __group, int gfp_mask);
30 void cn_netlink_send(struct cn_msg *msg, u32 portid, u32 __group, int gfp_mask);
31
32 struct cb_id
33 {
34 __u32 idx;
35 __u32 val;
36 };
37
38 idx and val are unique identifiers which must be registered in the
39 connector.h header for in-kernel usage. `void (*callback) (void *)` is a
40 callback function which will be called when a message with above idx.val
41 is received by the connector core. The argument for that function must
42 be dereferenced to `struct cn_msg *`::
43
44 struct cn_msg
45 {
46 struct cb_id id;
47
48 __u32 seq;
49 __u32 ack;
50
51 __u16 len; /* Length of the following data */
52 __u16 flags;
53 __u8 data[0];
54 };
55
56 Connector interfaces
57 ====================
58
59 .. kernel-doc:: include/linux/connector.h
60
61 Note:
62 When registering new callback user, connector core assigns
63 netlink group to the user which is equal to its id.idx.
64
65 Protocol description
66 ====================
67
68 The current framework offers a transport layer with fixed headers. The
69 recommended protocol which uses such a header is as following:
70
71 msg->seq and msg->ack are used to determine message genealogy. When
72 someone sends a message, they use a locally unique sequence and random
73 acknowledge number. The sequence number may be copied into
74 nlmsghdr->nlmsg_seq too.
75
76 The sequence number is incremented with each message sent.
77
78 If you expect a reply to the message, then the sequence number in the
79 received message MUST be the same as in the original message, and the
80 acknowledge number MUST be the same + 1.
81
82 If we receive a message and its sequence number is not equal to one we
83 are expecting, then it is a new message. If we receive a message and
84 its sequence number is the same as one we are expecting, but its
85 acknowledge is not equal to the sequence number in the original
86 message + 1, then it is a new message.
87
88 Obviously, the protocol header contains the above id.
89
90 The connector allows event notification in the following form: kernel
91 driver or userspace process can ask connector to notify it when
92 selected ids will be turned on or off (registered or unregistered its
93 callback). It is done by sending a special command to the connector
94 driver (it also registers itself with id={-1, -1}).
95
96 As example of this usage can be found in the cn_test.c module which
97 uses the connector to request notification and to send messages.
98
99 Reliability
100 ===========
101
102 Netlink itself is not a reliable protocol. That means that messages can
103 be lost due to memory pressure or process' receiving queue overflowed,
104 so caller is warned that it must be prepared. That is why the struct
105 cn_msg [main connector's message header] contains u32 seq and u32 ack
106 fields.
107
108 Userspace usage
109 ===============
110
111 2.6.14 has a new netlink socket implementation, which by default does not
112 allow people to send data to netlink groups other than 1.
113 So, if you wish to use a netlink socket (for example using connector)
114 with a different group number, the userspace application must subscribe to
115 that group first. It can be achieved by the following pseudocode::
116
117 s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
118
119 l_local.nl_family = AF_NETLINK;
120 l_local.nl_groups = 12345;
121 l_local.nl_pid = 0;
122
123 if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
124 perror("bind");
125 close(s);
126 return -1;
127 }
128
129 {
130 int on = l_local.nl_groups;
131 setsockopt(s, 270, 1, &on, sizeof(on));
132 }
133
134 Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket
135 option. To drop a multicast subscription, one should call the above socket
136 option with the NETLINK_DROP_MEMBERSHIP parameter which is defined as 0.
137
138 2.6.14 netlink code only allows to select a group which is less or equal to
139 the maximum group number, which is used at netlink_kernel_create() time.
140 In case of connector it is CN_NETLINK_USERS + 0xf, so if you want to use
141 group number 12345, you must increment CN_NETLINK_USERS to that number.
142 Additional 0xf numbers are allocated to be used by non-in-kernel users.
143
144 Due to this limitation, group 0xffffffff does not work now, so one can
145 not use add/remove connector's group notifications, but as far as I know,
146 only cn_test.c test module used it.
147
148 Some work in netlink area is still being done, so things can be changed in
149 2.6.15 timeframe, if it will happen, documentation will be updated for that
150 kernel.
151
152 Code samples
153 ============
154
155 Sample code for a connector test module and user space can be found
156 in samples/connector/. To build this code, enable CONFIG_CONNECTOR
157 and CONFIG_SAMPLES.
158

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Kernel Connector 개요

1-14
.. SPDX-License-Identifier: GPL-2.0

Kernel Connector는 netlink를 기반으로 사용자 공간과 커널 공간이 쉽게 통신하게 하는 모듈입니다.

Connector 드라이버는 netlink 기반 네트워크로 여러 에이전트를 쉽게 연결합니다. 콜백과 식별자를 등록하면, 드라이버가 해당 식별자가 담긴 특수 netlink 메시지를 받았을 때 알맞은 콜백을 호출합니다.

사용자 공간 절차와 커널 API

15-55

사용자 공간에서는 `socket()`, `bind()`, `send()`, `recv()` 순서로 비교적 간단히 사용합니다.

- socket();
- bind();
- send();
- recv();

커널 공간에서 이 연결의 모든 기능을 직접 사용하려면 전용 소켓을 만들고 `struct sk_buff` 처리 방법도 알아야 합니다. Connector는 커널 에이전트가 netlink 기반 프로세스 간 통신을 훨씬 쉽게 사용하도록 콜백 등록과 메시지 전송 API를 제공합니다.

int cn_add_callback(const struct cb_id *id, char *name, void (*callback) (struct cn_msg *, struct netlink_skb_parms *));
void cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 __group, int gfp_mask);
void cn_netlink_send(struct cn_msg *msg, u32 portid, u32 __group, int gfp_mask);

struct cb_id
{
      __u32                        idx;
      __u32                        val;
};

`idx`와 `val`은 커널 내부 사용을 위해 `connector.h`에 등록해야 하는 고유 식별자입니다. `void (*callback) (void *)` 콜백은 Connector 코어가 해당 `idx.val`을 가진 메시지를 받을 때 호출하며, 인자는 `struct cn_msg *`로 역참조해야 합니다.

struct cn_msg
{
      struct cb_id                id;

      __u32                        seq;
      __u32                        ack;

      __u16                        len;        /* Length of the following data */
      __u16                        flags;
      __u8                        data[0];
};

`struct cn_msg`는 `struct cb_id id`, 계보 추적용 `seq`와 `ack`, 뒤따르는 데이터 길이 `len`, `flags`, 가변 데이터 `data[0]`을 담습니다.

Connector 인터페이스

56-64

Connector 인터페이스는 `include/linux/connector.h`의 kernel-doc으로 제공됩니다.

.. kernel-doc:: include/linux/connector.h

새 콜백 사용자를 등록할 때 Connector 코어는 사용자의 `id.idx`와 같은 번호의 netlink 그룹을 할당합니다.

프로토콜과 메시지 계보

65-98

현재 프레임워크는 고정 헤더를 가진 전송 계층을 제공합니다. 권장 프로토콜은 `msg->seq`와 `msg->ack`로 메시지 계보를 판별합니다. 송신자는 로컬에서 고유한 sequence와 임의의 acknowledge 번호를 사용하며, sequence를 `nlmsghdr->nlmsg_seq`에도 복사할 수 있습니다.

sequence 번호는 메시지를 보낼 때마다 증가합니다. 답장을 기대한다면 수신 메시지의 sequence는 원본 메시지와 같아야 하고 acknowledge는 원본 값에 1을 더한 값이어야 합니다.

수신 sequence가 기대한 값과 다르면 새 메시지입니다. sequence는 기대값과 같지만 acknowledge가 원본 sequence + 1이 아니어도 새 메시지입니다. 프로토콜 헤더에는 앞서 설명한 `id`도 포함됩니다.

Connector는 선택한 ID의 콜백이 등록되거나 해제될 때 커널 드라이버나 사용자 공간 프로세스에 알리는 이벤트 통지를 지원합니다. Connector 드라이버에 특수 명령을 보내 요청하며, 드라이버 자신도 `id={-1, -1}`로 등록합니다.

`cn_test.c` 모듈은 Connector로 통지를 요청하고 메시지를 보내는 사용 예를 제공합니다.

신뢰성

99-107

netlink 자체는 신뢰성 있는 프로토콜이 아닙니다. 메모리 부족이나 프로세스 수신 큐 overflow로 메시지를 잃을 수 있으므로 호출자는 이에 대비해야 합니다.

이 때문에 Connector의 주 메시지 헤더인 `struct cn_msg`에는 `u32 seq`와 `u32 ack` 필드가 있습니다.

사용자 공간에서 netlink 그룹 사용

108-150

Linux 2.6.14의 새 netlink 소켓 구현은 기본적으로 그룹 1이 아닌 netlink 그룹으로 데이터를 보내지 못하게 합니다. 다른 그룹 번호로 Connector 같은 netlink 소켓을 사용하려면 사용자 공간 애플리케이션이 먼저 해당 그룹을 구독해야 합니다.

s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);

l_local.nl_family = AF_NETLINK;
l_local.nl_groups = 12345;
l_local.nl_pid = 0;

if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
      perror("bind");
      close(s);
      return -1;
}

{
      int on = l_local.nl_groups;
      setsockopt(s, 270, 1, &on, sizeof(on));
}

위 코드의 `270`은 `SOL_NETLINK`, `1`은 `NETLINK_ADD_MEMBERSHIP` 소켓 옵션입니다. multicast 구독을 해제하려면 같은 소켓 옵션을 값 `0`으로 정의된 `NETLINK_DROP_MEMBERSHIP` 매개변수와 함께 호출합니다.

2.6.14 netlink 코드는 `netlink_kernel_create()` 때 사용한 최대 그룹 번호 이하만 선택할 수 있습니다. Connector의 최대값은 `CN_NETLINK_USERS + 0xf`이므로 그룹 `12345`를 사용하려면 `CN_NETLINK_USERS`를 그 값까지 늘려야 합니다. 추가 `0xf`개 번호는 커널 외부 사용자를 위해 할당됩니다.

이 제한 때문에 그룹 `0xffffffff`는 현재 동작하지 않아 Connector 그룹의 추가 및 제거 통지를 사용할 수 없습니다. 당시 알려진 사용자로는 `cn_test.c` 테스트 모듈만 있었습니다.

netlink 영역의 작업은 계속 진행 중이었으므로 2.6.15 시기에 동작이 바뀔 수 있으며, 변경되면 해당 커널 문서를 갱신할 예정이라고 원문은 설명합니다.

코드 예제

151-157

Connector 테스트 모듈과 사용자 공간 예제 코드는 `samples/connector/`에 있습니다. 빌드하려면 `CONFIG_CONNECTOR`와 `CONFIG_SAMPLES`를 활성화합니다.