Blame view

Documentation/networking/kcm.txt 10.7 KB
10016594f   Tom Herbert   kcm: Add descript...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  Kernel Connection Mulitplexor
  -----------------------------
  
  Kernel Connection Multiplexor (KCM) is a mechanism that provides a message based
  interface over TCP for generic application protocols. With KCM an application
  can efficiently send and receive application protocol messages over TCP using
  datagram sockets.
  
  KCM implements an NxM multiplexor in the kernel as diagrammed below:
  
  +------------+   +------------+   +------------+   +------------+
  | KCM socket |   | KCM socket |   | KCM socket |   | KCM socket |
  +------------+   +------------+   +------------+   +------------+
        |                 |               |                |
        +-----------+     |               |     +----------+
                    |     |               |     |
                 +----------------------------------+
                 |           Multiplexor            |
                 +----------------------------------+
                   |   |           |           |  |
         +---------+   |           |           |  ------------+
         |             |           |           |              |
  +----------+  +----------+  +----------+  +----------+ +----------+
  |  Psock   |  |  Psock   |  |  Psock   |  |  Psock   | |  Psock   |
  +----------+  +----------+  +----------+  +----------+ +----------+
        |              |           |            |             |
  +----------+  +----------+  +----------+  +----------+ +----------+
  | TCP sock |  | TCP sock |  | TCP sock |  | TCP sock | | TCP sock |
  +----------+  +----------+  +----------+  +----------+ +----------+
  
  KCM sockets
  -----------
  
  The KCM sockets provide the user interface to the muliplexor. All the KCM sockets
  bound to a multiplexor are considered to have equivalent function, and I/O
  operations in different sockets may be done in parallel without the need for
  synchronization between threads in userspace.
  
  Multiplexor
  -----------
  
  The multiplexor provides the message steering. In the transmit path, messages
  written on a KCM socket are sent atomically on an appropriate TCP socket.
  Similarly, in the receive path, messages are constructed on each TCP socket
  (Psock) and complete messages are steered to a KCM socket.
  
  TCP sockets & Psocks
  --------------------
  
  TCP sockets may be bound to a KCM multiplexor. A Psock structure is allocated
  for each bound TCP socket, this structure holds the state for constructing
  messages on receive as well as other connection specific information for KCM.
  
  Connected mode semantics
  ------------------------
  
  Each multiplexor assumes that all attached TCP connections are to the same
  destination and can use the different connections for load balancing when
  transmitting. The normal send and recv calls (include sendmmsg and recvmmsg)
  can be used to send and receive messages from the KCM socket.
  
  Socket types
  ------------
  
  KCM supports SOCK_DGRAM and SOCK_SEQPACKET socket types.
  
  Message delineation
  -------------------
  
  Messages are sent over a TCP stream with some application protocol message
  format that typically includes a header which frames the messages. The length
  of a received message can be deduced from the application protocol header
  (often just a simple length field).
  
  A TCP stream must be parsed to determine message boundaries. Berkeley Packet
  Filter (BPF) is used for this. When attaching a TCP socket to a multiplexor a
  BPF program must be specified. The program is called at the start of receiving
  a new message and is given an skbuff that contains the bytes received so far.
  It parses the message header and returns the length of the message. Given this
  information, KCM will construct the message of the stated length and deliver it
  to a KCM socket.
  
  TCP socket management
  ---------------------
  
  When a TCP socket is attached to a KCM multiplexor data ready (POLLIN) and
  write space available (POLLOUT) events are handled by the multiplexor. If there
  is a state change (disconnection) or other error on a TCP socket, an error is
  posted on the TCP socket so that a POLLERR event happens and KCM discontinues
  using the socket. When the application gets the error notification for a
  TCP socket, it should unattach the socket from KCM and then handle the error
  condition (the typical response is to close the socket and create a new
  connection if necessary).
  
  KCM limits the maximum receive message size to be the size of the receive
  socket buffer on the attached TCP socket (the socket buffer size can be set by
  SO_RCVBUF). If the length of a new message reported by the BPF program is
  greater than this limit a corresponding error (EMSGSIZE) is posted on the TCP
  socket. The BPF program may also enforce a maximum messages size and report an
  error when it is exceeded.
  
  A timeout may be set for assembling messages on a receive socket. The timeout
  value is taken from the receive timeout of the attached TCP socket (this is set
  by SO_RCVTIMEO). If the timer expires before assembly is complete an error
  (ETIMEDOUT) is posted on the socket.
  
  User interface
  ==============
  
  Creating a multiplexor
  ----------------------
  
  A new multiplexor and initial KCM socket is created by a socket call:
  
    socket(AF_KCM, type, protocol)
  
    - type is either SOCK_DGRAM or SOCK_SEQPACKET
    - protocol is KCMPROTO_CONNECTED
  
  Cloning KCM sockets
  -------------------
  
  After the first KCM socket is created using the socket call as described
  above, additional sockets for the multiplexor can be created by cloning
  a KCM socket. This is accomplished by an ioctl on a KCM socket:
  
    /* From linux/kcm.h */
    struct kcm_clone {
          int fd;
    };
  
    struct kcm_clone info;
  
    memset(&info, 0, sizeof(info));
  
    err = ioctl(kcmfd, SIOCKCMCLONE, &info);
  
    if (!err)
      newkcmfd = info.fd;
  
  Attach transport sockets
  ------------------------
  
  Attaching of transport sockets to a multiplexor is performed by calling an
  ioctl on a KCM socket for the multiplexor. e.g.:
  
    /* From linux/kcm.h */
    struct kcm_attach {
          int fd;
  	int bpf_fd;
    };
  
    struct kcm_attach info;
  
    memset(&info, 0, sizeof(info));
  
    info.fd = tcpfd;
    info.bpf_fd = bpf_prog_fd;
  
    ioctl(kcmfd, SIOCKCMATTACH, &info);
  
  The kcm_attach structure contains:
    fd: file descriptor for TCP socket being attached
    bpf_prog_fd: file descriptor for compiled BPF program downloaded
  
  Unattach transport sockets
  --------------------------
  
  Unattaching a transport socket from a multiplexor is straightforward. An
  "unattach" ioctl is done with the kcm_unattach structure as the argument:
  
    /* From linux/kcm.h */
    struct kcm_unattach {
          int fd;
    };
  
    struct kcm_unattach info;
  
    memset(&info, 0, sizeof(info));
  
    info.fd = cfd;
  
    ioctl(fd, SIOCKCMUNATTACH, &info);
  
  Disabling receive on KCM socket
  -------------------------------
  
  A setsockopt is used to disable or enable receiving on a KCM socket.
  When receive is disabled, any pending messages in the socket's
  receive buffer are moved to other sockets. This feature is useful
  if an application thread knows that it will be doing a lot of
  work on a request and won't be able to service new messages for a
  while. Example use:
  
    int val = 1;
  
    setsockopt(kcmfd, SOL_KCM, KCM_RECV_DISABLE, &val, sizeof(val))
  
  BFP programs for message delineation
  ------------------------------------
  
  BPF programs can be compiled using the BPF LLVM backend. For exmple,
  the BPF program for parsing Thrift is:
  
    #include "bpf.h" /* for __sk_buff */
    #include "bpf_helpers.h" /* for load_word intrinsic */
  
    SEC("socket_kcm")
    int bpf_prog1(struct __sk_buff *skb)
    {
         return load_word(skb, 0) + 4;
    }
  
    char _license[] SEC("license") = "GPL";
  
  Use in applications
  ===================
  
  KCM accelerates application layer protocols. Specifically, it allows
  applications to use a message based interface for sending and receiving
  messages. The kernel provides necessary assurances that messages are sent
  and received atomically. This relieves much of the burden applications have
  in mapping a message based protocol onto the TCP stream. KCM also make
  application layer messages a unit of work in the kernel for the purposes of
  steerng and scheduling, which in turn allows a simpler networking model in
  multithreaded applications.
  
  Configurations
  --------------
  
  In an Nx1 configuration, KCM logically provides multiple socket handles
  to the same TCP connection. This allows parallelism between in I/O
  operations on the TCP socket (for instance copyin and copyout of data is
  parallelized). In an application, a KCM socket can be opened for each
  processing thread and inserted into the epoll (similar to how SO_REUSEPORT
  is used to allow multiple listener sockets on the same port).
  
  In a MxN configuration, multiple connections are established to the
  same destination. These are used for simple load balancing.
  
  Message batching
  ----------------
  
  The primary purpose of KCM is load balancing between KCM sockets and hence
  threads in a nominal use case. Perfect load balancing, that is steering
  each received message to a different KCM socket or steering each sent
  message to a different TCP socket, can negatively impact performance
  since this doesn't allow for affinities to be established. Balancing
  based on groups, or batches of messages, can be beneficial for performance.
  
  On transmit, there are three ways an application can batch (pipeline)
  messages on a KCM socket.
    1) Send multiple messages in a single sendmmsg.
    2) Send a group of messages each with a sendmsg call, where all messages
       except the last have MSG_BATCH in the flags of sendmsg call.
    3) Create "super message" composed of multiple messages and send this
       with a single sendmsg.
  
  On receive, the KCM module attempts to queue messages received on the
  same KCM socket during each TCP ready callback. The targeted KCM socket
  changes at each receive ready callback on the KCM socket. The application
  does not need to configure this.
  
  Error handling
  --------------
  
  An application should include a thread to monitor errors raised on
  the TCP connection. Normally, this will be done by placing each
  TCP socket attached to a KCM multiplexor in epoll set for POLLERR
  event. If an error occurs on an attached TCP socket, KCM sets an EPIPE
  on the socket thus waking up the application thread. When the application
  sees the error (which may just be a disconnect) it should unattach the
  socket from KCM and then close it. It is assumed that once an error is
  posted on the TCP socket the data stream is unrecoverable (i.e. an error
  may have occurred in in the middle of receiving a messssge).
  
  TCP connection monitoring
  -------------------------
  
  In KCM there is no means to correlate a message to the TCP socket that
  was used to send or receive the message (except in the case there is
  only one attached TCP socket). However, the application does retain
  an open file descriptor to the socket so it will be able to get statistics
  from the socket which can be used in detecting issues (such as high
  retransmissions on the socket).