/src/openvswitch/lib/netlink-socket.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Nicira, Inc. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at: |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include <config.h> |
18 | | #include "netlink-socket.h" |
19 | | #include <errno.h> |
20 | | #include <inttypes.h> |
21 | | #include <stdlib.h> |
22 | | #include <sys/socket.h> |
23 | | #include <sys/types.h> |
24 | | #include <sys/uio.h> |
25 | | #include <unistd.h> |
26 | | #include "coverage.h" |
27 | | #include "openvswitch/dynamic-string.h" |
28 | | #include "hash.h" |
29 | | #include "openvswitch/hmap.h" |
30 | | #include "netlink.h" |
31 | | #include "netlink-protocol.h" |
32 | | #include "netnsid.h" |
33 | | #include "odp-netlink.h" |
34 | | #include "openvswitch/ofpbuf.h" |
35 | | #include "ovs-thread.h" |
36 | | #include "openvswitch/poll-loop.h" |
37 | | #include "seq.h" |
38 | | #include "socket-util.h" |
39 | | #include "util.h" |
40 | | #include "openvswitch/vlog.h" |
41 | | |
42 | | VLOG_DEFINE_THIS_MODULE(netlink_socket); |
43 | | |
44 | | COVERAGE_DEFINE(netlink_overflow); |
45 | | COVERAGE_DEFINE(netlink_received); |
46 | | COVERAGE_DEFINE(netlink_recv_jumbo); |
47 | | COVERAGE_DEFINE(netlink_sent); |
48 | | |
49 | | /* Linux header file confusion causes this to be undefined. */ |
50 | | #ifndef SOL_NETLINK |
51 | | #define SOL_NETLINK 270 |
52 | | #endif |
53 | | |
54 | | /* A single (bad) Netlink message can in theory dump out many, many log |
55 | | * messages, so the burst size is set quite high here to avoid missing useful |
56 | | * information. Also, at high logging levels we log *all* Netlink messages. */ |
57 | | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 600); |
58 | | |
59 | | static uint32_t nl_sock_allocate_seq(struct nl_sock *, unsigned int n); |
60 | | static void log_nlmsg(const char *function, int error, |
61 | | const void *message, size_t size, int protocol); |
62 | | #ifdef _WIN32 |
63 | | static int get_sock_pid_from_kernel(struct nl_sock *sock); |
64 | | static int set_sock_property(struct nl_sock *sock); |
65 | | static int nl_sock_transact(struct nl_sock *sock, const struct ofpbuf *request, |
66 | | struct ofpbuf **replyp); |
67 | | |
68 | | /* In the case DeviceIoControl failed and GetLastError returns with |
69 | | * ERROR_NOT_FOUND means we lost communication with the kernel device. |
70 | | * CloseHandle will fail because the handle in 'theory' does not exist. |
71 | | * The only remaining option is to crash and allow the service to be restarted |
72 | | * via service manager. This is the only way to close the handle from both |
73 | | * userspace and kernel. */ |
74 | | void |
75 | | lost_communication(DWORD last_err) |
76 | | { |
77 | | if (last_err == ERROR_NOT_FOUND) { |
78 | | ovs_abort(0, "lost communication with the kernel device"); |
79 | | } |
80 | | } |
81 | | #endif |
82 | | |
83 | | /* Netlink sockets. */ |
84 | | |
85 | | struct nl_sock { |
86 | | #ifdef _WIN32 |
87 | | HANDLE handle; |
88 | | OVERLAPPED overlapped; |
89 | | DWORD read_ioctl; |
90 | | #else |
91 | | int fd; |
92 | | #endif |
93 | | uint32_t next_seq; |
94 | | uint32_t pid; |
95 | | int protocol; |
96 | | unsigned int rcvbuf; /* Receive buffer size (SO_RCVBUF). */ |
97 | | }; |
98 | | |
99 | | /* Compile-time limit on iovecs, so that we can allocate a maximum-size array |
100 | | * of iovecs on the stack. */ |
101 | 0 | #define MAX_IOVS 128 |
102 | | |
103 | | /* Maximum number of iovecs that may be passed to sendmsg, capped at a |
104 | | * minimum of _XOPEN_IOV_MAX (16) and a maximum of MAX_IOVS. |
105 | | * |
106 | | * Initialized by nl_sock_create(). */ |
107 | | static int max_iovs; |
108 | | |
109 | | static int nl_pool_alloc(int protocol, struct nl_sock **sockp); |
110 | | static void nl_pool_release(struct nl_sock *); |
111 | | |
112 | | /* Creates a new netlink socket for the given netlink 'protocol' |
113 | | * (NETLINK_ROUTE, NETLINK_GENERIC, ...). Returns 0 and sets '*sockp' to the |
114 | | * new socket if successful, otherwise returns a positive errno value. */ |
115 | | int |
116 | | nl_sock_create(int protocol, struct nl_sock **sockp) |
117 | 0 | { |
118 | 0 | static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; |
119 | 0 | struct nl_sock *sock; |
120 | 0 | #ifndef _WIN32 |
121 | 0 | struct sockaddr_nl local, remote; |
122 | 0 | int one = 1; |
123 | 0 | #endif |
124 | 0 | socklen_t local_size; |
125 | 0 | int rcvbuf; |
126 | 0 | int retval = 0; |
127 | |
|
128 | 0 | if (ovsthread_once_start(&once)) { |
129 | 0 | int save_errno = errno; |
130 | 0 | errno = 0; |
131 | |
|
132 | 0 | max_iovs = sysconf(_SC_UIO_MAXIOV); |
133 | 0 | if (max_iovs < _XOPEN_IOV_MAX) { |
134 | 0 | if (max_iovs == -1 && errno) { |
135 | 0 | VLOG_WARN("sysconf(_SC_UIO_MAXIOV): %s", ovs_strerror(errno)); |
136 | 0 | } |
137 | 0 | max_iovs = _XOPEN_IOV_MAX; |
138 | 0 | } else if (max_iovs > MAX_IOVS) { |
139 | 0 | max_iovs = MAX_IOVS; |
140 | 0 | } |
141 | |
|
142 | 0 | errno = save_errno; |
143 | 0 | ovsthread_once_done(&once); |
144 | 0 | } |
145 | |
|
146 | 0 | *sockp = NULL; |
147 | 0 | sock = xmalloc(sizeof *sock); |
148 | |
|
149 | | #ifdef _WIN32 |
150 | | sock->overlapped.hEvent = NULL; |
151 | | sock->handle = CreateFile(OVS_DEVICE_NAME_USER, |
152 | | GENERIC_READ | GENERIC_WRITE, |
153 | | FILE_SHARE_READ | FILE_SHARE_WRITE, |
154 | | NULL, OPEN_EXISTING, |
155 | | FILE_FLAG_OVERLAPPED, NULL); |
156 | | |
157 | | if (sock->handle == INVALID_HANDLE_VALUE) { |
158 | | VLOG_ERR("fcntl: %s", ovs_lasterror_to_string()); |
159 | | goto error; |
160 | | } |
161 | | |
162 | | memset(&sock->overlapped, 0, sizeof sock->overlapped); |
163 | | sock->overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
164 | | if (sock->overlapped.hEvent == NULL) { |
165 | | VLOG_ERR("fcntl: %s", ovs_lasterror_to_string()); |
166 | | goto error; |
167 | | } |
168 | | /* Initialize the type/ioctl to Generic */ |
169 | | sock->read_ioctl = OVS_IOCTL_READ; |
170 | | #else |
171 | 0 | sock->fd = socket(AF_NETLINK, SOCK_RAW, protocol); |
172 | 0 | if (sock->fd < 0) { |
173 | 0 | VLOG_ERR("fcntl: %s", ovs_strerror(errno)); |
174 | 0 | goto error; |
175 | 0 | } |
176 | 0 | #endif |
177 | | |
178 | 0 | sock->protocol = protocol; |
179 | 0 | sock->next_seq = 1; |
180 | |
|
181 | 0 | rcvbuf = 1024 * 1024 * 4; |
182 | | #ifdef _WIN32 |
183 | | sock->rcvbuf = rcvbuf; |
184 | | retval = get_sock_pid_from_kernel(sock); |
185 | | if (retval != 0) { |
186 | | goto error; |
187 | | } |
188 | | retval = set_sock_property(sock); |
189 | | if (retval != 0) { |
190 | | goto error; |
191 | | } |
192 | | #else |
193 | 0 | if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_EXT_ACK, &one, sizeof one)) { |
194 | 0 | VLOG_WARN_RL(&rl, "setting extended ack support failed (%s)", |
195 | 0 | ovs_strerror(errno)); |
196 | 0 | } |
197 | |
|
198 | 0 | if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUFFORCE, |
199 | 0 | &rcvbuf, sizeof rcvbuf)) { |
200 | | /* Only root can use SO_RCVBUFFORCE. Everyone else gets EPERM. |
201 | | * Warn only if the failure is therefore unexpected. */ |
202 | 0 | if (errno != EPERM) { |
203 | 0 | VLOG_WARN_RL(&rl, "setting %d-byte socket receive buffer failed " |
204 | 0 | "(%s)", rcvbuf, ovs_strerror(errno)); |
205 | 0 | } |
206 | 0 | } |
207 | | |
208 | | /* Strict checking only supported for NETLINK_ROUTE. */ |
209 | 0 | if (protocol == NETLINK_ROUTE |
210 | 0 | && setsockopt(sock->fd, SOL_NETLINK, NETLINK_GET_STRICT_CHK, |
211 | 0 | &one, sizeof one) < 0) { |
212 | 0 | VLOG_RL(&rl, errno == ENOPROTOOPT ? VLL_DBG : VLL_WARN, |
213 | 0 | "netlink: could not enable strict checking (%s)", |
214 | 0 | ovs_strerror(errno)); |
215 | 0 | } |
216 | |
|
217 | 0 | retval = get_socket_rcvbuf(sock->fd); |
218 | 0 | if (retval < 0) { |
219 | 0 | retval = -retval; |
220 | 0 | goto error; |
221 | 0 | } |
222 | 0 | sock->rcvbuf = retval; |
223 | 0 | retval = 0; |
224 | | |
225 | | /* Connect to kernel (pid 0) as remote address. */ |
226 | 0 | memset(&remote, 0, sizeof remote); |
227 | 0 | remote.nl_family = AF_NETLINK; |
228 | 0 | remote.nl_pid = 0; |
229 | 0 | if (connect(sock->fd, (struct sockaddr *) &remote, sizeof remote) < 0) { |
230 | 0 | VLOG_ERR("connect(0): %s", ovs_strerror(errno)); |
231 | 0 | goto error; |
232 | 0 | } |
233 | | |
234 | | /* Obtain pid assigned by kernel. */ |
235 | 0 | memset(&local, 0, sizeof local); |
236 | 0 | local_size = sizeof local; |
237 | 0 | if (getsockname(sock->fd, (struct sockaddr *) &local, &local_size) < 0) { |
238 | 0 | VLOG_ERR("getsockname: %s", ovs_strerror(errno)); |
239 | 0 | goto error; |
240 | 0 | } |
241 | 0 | if (local_size < sizeof local || local.nl_family != AF_NETLINK) { |
242 | 0 | VLOG_ERR("getsockname returned bad Netlink name"); |
243 | 0 | retval = EINVAL; |
244 | 0 | goto error; |
245 | 0 | } |
246 | 0 | sock->pid = local.nl_pid; |
247 | 0 | #endif |
248 | |
|
249 | 0 | *sockp = sock; |
250 | 0 | return 0; |
251 | | |
252 | 0 | error: |
253 | 0 | if (retval == 0) { |
254 | 0 | retval = errno; |
255 | 0 | if (retval == 0) { |
256 | 0 | retval = EINVAL; |
257 | 0 | } |
258 | 0 | } |
259 | | #ifdef _WIN32 |
260 | | if (sock->overlapped.hEvent) { |
261 | | CloseHandle(sock->overlapped.hEvent); |
262 | | } |
263 | | if (sock->handle != INVALID_HANDLE_VALUE) { |
264 | | CloseHandle(sock->handle); |
265 | | } |
266 | | #else |
267 | 0 | if (sock->fd >= 0) { |
268 | 0 | close(sock->fd); |
269 | 0 | } |
270 | 0 | #endif |
271 | 0 | free(sock); |
272 | 0 | return retval; |
273 | 0 | } |
274 | | |
275 | | /* Creates a new netlink socket for the same protocol as 'src'. Returns 0 and |
276 | | * sets '*sockp' to the new socket if successful, otherwise returns a positive |
277 | | * errno value. */ |
278 | | int |
279 | | nl_sock_clone(const struct nl_sock *src, struct nl_sock **sockp) |
280 | 0 | { |
281 | 0 | return nl_sock_create(src->protocol, sockp); |
282 | 0 | } |
283 | | |
284 | | /* Destroys netlink socket 'sock'. */ |
285 | | void |
286 | | nl_sock_destroy(struct nl_sock *sock) |
287 | 0 | { |
288 | 0 | if (sock) { |
289 | | #ifdef _WIN32 |
290 | | if (sock->overlapped.hEvent) { |
291 | | CloseHandle(sock->overlapped.hEvent); |
292 | | } |
293 | | CloseHandle(sock->handle); |
294 | | #else |
295 | 0 | close(sock->fd); |
296 | 0 | #endif |
297 | 0 | free(sock); |
298 | 0 | } |
299 | 0 | } |
300 | | |
301 | | #ifdef _WIN32 |
302 | | /* Reads the pid for 'sock' generated in the kernel datapath. The function |
303 | | * uses a separate IOCTL instead of a transaction semantic to avoid unnecessary |
304 | | * message overhead. */ |
305 | | static int |
306 | | get_sock_pid_from_kernel(struct nl_sock *sock) |
307 | | { |
308 | | uint32_t pid = 0; |
309 | | int retval = 0; |
310 | | DWORD bytes = 0; |
311 | | |
312 | | if (!DeviceIoControl(sock->handle, OVS_IOCTL_GET_PID, |
313 | | NULL, 0, &pid, sizeof(pid), |
314 | | &bytes, NULL)) { |
315 | | lost_communication(GetLastError()); |
316 | | retval = EINVAL; |
317 | | } else { |
318 | | if (bytes < sizeof(pid)) { |
319 | | retval = EINVAL; |
320 | | } else { |
321 | | sock->pid = pid; |
322 | | } |
323 | | } |
324 | | |
325 | | return retval; |
326 | | } |
327 | | |
328 | | /* Used for setting and managing socket properties in userspace and kernel. |
329 | | * Currently two attributes are tracked - pid and protocol |
330 | | * protocol - supplied by userspace based on the netlink family. Windows uses |
331 | | * this property to set the value in kernel datapath. |
332 | | * eg: (NETLINK_GENERIC/ NETLINK_NETFILTER) |
333 | | * pid - generated by windows kernel and set in userspace. The property |
334 | | * is not modified. |
335 | | * Also verify if Protocol and PID in Kernel reflects the values in userspace |
336 | | * */ |
337 | | static int |
338 | | set_sock_property(struct nl_sock *sock) |
339 | | { |
340 | | static const struct nl_policy ovs_socket_policy[] = { |
341 | | [OVS_NL_ATTR_SOCK_PROTO] = { .type = NL_A_BE32, .optional = true }, |
342 | | [OVS_NL_ATTR_SOCK_PID] = { .type = NL_A_BE32, .optional = true } |
343 | | }; |
344 | | |
345 | | struct ofpbuf request, *reply; |
346 | | struct ovs_header *ovs_header; |
347 | | struct nlattr *attrs[ARRAY_SIZE(ovs_socket_policy)]; |
348 | | int retval = 0; |
349 | | int error; |
350 | | |
351 | | ofpbuf_init(&request, 0); |
352 | | nl_msg_put_genlmsghdr(&request, 0, OVS_WIN_NL_CTRL_FAMILY_ID, 0, |
353 | | OVS_CTRL_CMD_SOCK_PROP, OVS_WIN_CONTROL_VERSION); |
354 | | ovs_header = ofpbuf_put_uninit(&request, sizeof *ovs_header); |
355 | | ovs_header->dp_ifindex = 0; |
356 | | |
357 | | nl_msg_put_be32(&request, OVS_NL_ATTR_SOCK_PROTO, sock->protocol); |
358 | | /* pid is already set as part of get_sock_pid_from_kernel() |
359 | | * This is added to maintain consistency |
360 | | */ |
361 | | nl_msg_put_be32(&request, OVS_NL_ATTR_SOCK_PID, sock->pid); |
362 | | |
363 | | error = nl_sock_transact(sock, &request, &reply); |
364 | | ofpbuf_uninit(&request); |
365 | | if (error) { |
366 | | retval = EINVAL; |
367 | | } |
368 | | |
369 | | if (!nl_policy_parse(reply, |
370 | | NLMSG_HDRLEN + GENL_HDRLEN + sizeof *ovs_header, |
371 | | ovs_socket_policy, attrs, |
372 | | ARRAY_SIZE(ovs_socket_policy))) { |
373 | | ofpbuf_delete(reply); |
374 | | retval = EINVAL; |
375 | | } |
376 | | /* Verify if the properties are setup properly */ |
377 | | if (attrs[OVS_NL_ATTR_SOCK_PROTO]) { |
378 | | int protocol = nl_attr_get_be32(attrs[OVS_NL_ATTR_SOCK_PROTO]); |
379 | | if (protocol != sock->protocol) { |
380 | | VLOG_ERR("Invalid protocol returned:%d expected:%d", |
381 | | protocol, sock->protocol); |
382 | | retval = EINVAL; |
383 | | } |
384 | | } |
385 | | |
386 | | if (attrs[OVS_NL_ATTR_SOCK_PID]) { |
387 | | int pid = nl_attr_get_be32(attrs[OVS_NL_ATTR_SOCK_PID]); |
388 | | if (pid != sock->pid) { |
389 | | VLOG_ERR("Invalid pid returned:%d expected:%d", |
390 | | pid, sock->pid); |
391 | | retval = EINVAL; |
392 | | } |
393 | | } |
394 | | |
395 | | return retval; |
396 | | } |
397 | | #endif /* _WIN32 */ |
398 | | |
399 | | #ifdef _WIN32 |
400 | | static int __inline |
401 | | nl_sock_mcgroup(struct nl_sock *sock, unsigned int multicast_group, bool join) |
402 | | { |
403 | | struct ofpbuf request; |
404 | | uint64_t request_stub[128]; |
405 | | struct ovs_header *ovs_header; |
406 | | struct nlmsghdr *nlmsg; |
407 | | int error; |
408 | | |
409 | | ofpbuf_use_stub(&request, request_stub, sizeof request_stub); |
410 | | |
411 | | nl_msg_put_genlmsghdr(&request, 0, OVS_WIN_NL_CTRL_FAMILY_ID, 0, |
412 | | OVS_CTRL_CMD_MC_SUBSCRIBE_REQ, |
413 | | OVS_WIN_CONTROL_VERSION); |
414 | | |
415 | | ovs_header = ofpbuf_put_uninit(&request, sizeof *ovs_header); |
416 | | ovs_header->dp_ifindex = 0; |
417 | | |
418 | | nl_msg_put_u32(&request, OVS_NL_ATTR_MCAST_GRP, multicast_group); |
419 | | nl_msg_put_u8(&request, OVS_NL_ATTR_MCAST_JOIN, join ? 1 : 0); |
420 | | |
421 | | error = nl_sock_send(sock, &request, true); |
422 | | ofpbuf_uninit(&request); |
423 | | return error; |
424 | | } |
425 | | #endif |
426 | | /* Tries to add 'sock' as a listener for 'multicast_group'. Returns 0 if |
427 | | * successful, otherwise a positive errno value. |
428 | | * |
429 | | * A socket that is subscribed to a multicast group that receives asynchronous |
430 | | * notifications must not be used for Netlink transactions or dumps, because |
431 | | * transactions and dumps can cause notifications to be lost. |
432 | | * |
433 | | * Multicast group numbers are always positive. |
434 | | * |
435 | | * It is not an error to attempt to join a multicast group to which a socket |
436 | | * already belongs. */ |
437 | | int |
438 | | nl_sock_join_mcgroup(struct nl_sock *sock, unsigned int multicast_group) |
439 | 0 | { |
440 | | #ifdef _WIN32 |
441 | | /* Set the socket type as a "multicast" socket */ |
442 | | sock->read_ioctl = OVS_IOCTL_READ_EVENT; |
443 | | int error = nl_sock_mcgroup(sock, multicast_group, true); |
444 | | if (error) { |
445 | | sock->read_ioctl = OVS_IOCTL_READ; |
446 | | VLOG_WARN("could not join multicast group %u (%s)", |
447 | | multicast_group, ovs_strerror(error)); |
448 | | return error; |
449 | | } |
450 | | #else |
451 | 0 | if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, |
452 | 0 | &multicast_group, sizeof multicast_group) < 0) { |
453 | 0 | VLOG_WARN("could not join multicast group %u (%s)", |
454 | 0 | multicast_group, ovs_strerror(errno)); |
455 | 0 | return errno; |
456 | 0 | } |
457 | 0 | #endif |
458 | 0 | return 0; |
459 | 0 | } |
460 | | |
461 | | /* When 'enable' is true, it tries to enable 'sock' to receive netlink |
462 | | * notifications form all network namespaces that have an nsid assigned |
463 | | * into the network namespace where the socket has been opened. The |
464 | | * running kernel needs to provide support for that. When 'enable' is |
465 | | * false, it will receive netlink notifications only from the network |
466 | | * namespace where the socket has been opened. |
467 | | * |
468 | | * Returns 0 if successful, otherwise a positive errno. */ |
469 | | int |
470 | | nl_sock_listen_all_nsid(struct nl_sock *sock, bool enable) |
471 | 0 | { |
472 | 0 | int error; |
473 | 0 | int val = enable ? 1 : 0; |
474 | |
|
475 | 0 | #ifndef _WIN32 |
476 | 0 | if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_LISTEN_ALL_NSID, &val, |
477 | 0 | sizeof val) < 0) { |
478 | 0 | error = errno; |
479 | 0 | VLOG_INFO("netlink: could not %s listening to all nsid (%s)", |
480 | 0 | enable ? "enable" : "disable", ovs_strerror(error)); |
481 | 0 | return errno; |
482 | 0 | } |
483 | 0 | #endif |
484 | | |
485 | 0 | return 0; |
486 | 0 | } |
487 | | |
488 | | #ifdef _WIN32 |
489 | | int |
490 | | nl_sock_subscribe_packet__(struct nl_sock *sock, bool subscribe) |
491 | | { |
492 | | struct ofpbuf request; |
493 | | uint64_t request_stub[128]; |
494 | | struct ovs_header *ovs_header; |
495 | | struct nlmsghdr *nlmsg; |
496 | | int error; |
497 | | |
498 | | ofpbuf_use_stub(&request, request_stub, sizeof request_stub); |
499 | | nl_msg_put_genlmsghdr(&request, 0, OVS_WIN_NL_CTRL_FAMILY_ID, 0, |
500 | | OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ, |
501 | | OVS_WIN_CONTROL_VERSION); |
502 | | |
503 | | ovs_header = ofpbuf_put_uninit(&request, sizeof *ovs_header); |
504 | | ovs_header->dp_ifindex = 0; |
505 | | nl_msg_put_u8(&request, OVS_NL_ATTR_PACKET_SUBSCRIBE, subscribe ? 1 : 0); |
506 | | nl_msg_put_u32(&request, OVS_NL_ATTR_PACKET_PID, sock->pid); |
507 | | |
508 | | error = nl_sock_send(sock, &request, true); |
509 | | ofpbuf_uninit(&request); |
510 | | return error; |
511 | | } |
512 | | |
513 | | int |
514 | | nl_sock_subscribe_packets(struct nl_sock *sock) |
515 | | { |
516 | | int error; |
517 | | |
518 | | if (sock->read_ioctl != OVS_IOCTL_READ) { |
519 | | return EINVAL; |
520 | | } |
521 | | |
522 | | error = nl_sock_subscribe_packet__(sock, true); |
523 | | if (error) { |
524 | | VLOG_WARN("could not subscribe packets (%s)", |
525 | | ovs_strerror(error)); |
526 | | return error; |
527 | | } |
528 | | sock->read_ioctl = OVS_IOCTL_READ_PACKET; |
529 | | |
530 | | return 0; |
531 | | } |
532 | | |
533 | | int |
534 | | nl_sock_unsubscribe_packets(struct nl_sock *sock) |
535 | | { |
536 | | ovs_assert(sock->read_ioctl == OVS_IOCTL_READ_PACKET); |
537 | | |
538 | | int error = nl_sock_subscribe_packet__(sock, false); |
539 | | if (error) { |
540 | | VLOG_WARN("could not unsubscribe to packets (%s)", |
541 | | ovs_strerror(error)); |
542 | | return error; |
543 | | } |
544 | | |
545 | | sock->read_ioctl = OVS_IOCTL_READ; |
546 | | return 0; |
547 | | } |
548 | | #endif |
549 | | |
550 | | /* Tries to make 'sock' stop listening to 'multicast_group'. Returns 0 if |
551 | | * successful, otherwise a positive errno value. |
552 | | * |
553 | | * Multicast group numbers are always positive. |
554 | | * |
555 | | * It is not an error to attempt to leave a multicast group to which a socket |
556 | | * does not belong. |
557 | | * |
558 | | * On success, reading from 'sock' will still return any messages that were |
559 | | * received on 'multicast_group' before the group was left. */ |
560 | | int |
561 | | nl_sock_leave_mcgroup(struct nl_sock *sock, unsigned int multicast_group) |
562 | 0 | { |
563 | | #ifdef _WIN32 |
564 | | int error = nl_sock_mcgroup(sock, multicast_group, false); |
565 | | if (error) { |
566 | | VLOG_WARN("could not leave multicast group %u (%s)", |
567 | | multicast_group, ovs_strerror(error)); |
568 | | return error; |
569 | | } |
570 | | sock->read_ioctl = OVS_IOCTL_READ; |
571 | | #else |
572 | 0 | if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, |
573 | 0 | &multicast_group, sizeof multicast_group) < 0) { |
574 | 0 | VLOG_WARN("could not leave multicast group %u (%s)", |
575 | 0 | multicast_group, ovs_strerror(errno)); |
576 | 0 | return errno; |
577 | 0 | } |
578 | 0 | #endif |
579 | 0 | return 0; |
580 | 0 | } |
581 | | |
582 | | static int |
583 | | nl_sock_send__(struct nl_sock *sock, const struct ofpbuf *msg, |
584 | | uint32_t nlmsg_seq, bool wait) |
585 | 0 | { |
586 | 0 | struct nlmsghdr *nlmsg = nl_msg_nlmsghdr(msg); |
587 | 0 | int error; |
588 | |
|
589 | 0 | nlmsg->nlmsg_len = msg->size; |
590 | 0 | nlmsg->nlmsg_seq = nlmsg_seq; |
591 | 0 | nlmsg->nlmsg_pid = sock->pid; |
592 | 0 | do { |
593 | 0 | int retval; |
594 | | #ifdef _WIN32 |
595 | | DWORD bytes; |
596 | | |
597 | | if (!DeviceIoControl(sock->handle, OVS_IOCTL_WRITE, |
598 | | msg->data, msg->size, NULL, 0, |
599 | | &bytes, NULL)) { |
600 | | lost_communication(GetLastError()); |
601 | | retval = -1; |
602 | | /* XXX: Map to a more appropriate error based on GetLastError(). */ |
603 | | errno = EINVAL; |
604 | | VLOG_DBG_RL(&rl, "fatal driver failure in write: %s", |
605 | | ovs_lasterror_to_string()); |
606 | | } else { |
607 | | retval = msg->size; |
608 | | } |
609 | | #else |
610 | 0 | retval = send(sock->fd, msg->data, msg->size, |
611 | 0 | wait ? 0 : MSG_DONTWAIT); |
612 | 0 | #endif |
613 | 0 | error = retval < 0 ? errno : 0; |
614 | 0 | } while (error == EINTR); |
615 | 0 | log_nlmsg(__func__, error, msg->data, msg->size, sock->protocol); |
616 | 0 | if (!error) { |
617 | 0 | COVERAGE_INC(netlink_sent); |
618 | 0 | } |
619 | 0 | return error; |
620 | 0 | } |
621 | | |
622 | | /* Tries to send 'msg', which must contain a Netlink message, to the kernel on |
623 | | * 'sock'. nlmsg_len in 'msg' will be finalized to match msg->size, nlmsg_pid |
624 | | * will be set to 'sock''s pid, and nlmsg_seq will be initialized to a fresh |
625 | | * sequence number, before the message is sent. |
626 | | * |
627 | | * Returns 0 if successful, otherwise a positive errno value. If |
628 | | * 'wait' is true, then the send will wait until buffer space is ready; |
629 | | * otherwise, returns EAGAIN if the 'sock' send buffer is full. */ |
630 | | int |
631 | | nl_sock_send(struct nl_sock *sock, const struct ofpbuf *msg, bool wait) |
632 | 0 | { |
633 | 0 | return nl_sock_send_seq(sock, msg, nl_sock_allocate_seq(sock, 1), wait); |
634 | 0 | } |
635 | | |
636 | | /* Tries to send 'msg', which must contain a Netlink message, to the kernel on |
637 | | * 'sock'. nlmsg_len in 'msg' will be finalized to match msg->size, nlmsg_pid |
638 | | * will be set to 'sock''s pid, and nlmsg_seq will be initialized to |
639 | | * 'nlmsg_seq', before the message is sent. |
640 | | * |
641 | | * Returns 0 if successful, otherwise a positive errno value. If |
642 | | * 'wait' is true, then the send will wait until buffer space is ready; |
643 | | * otherwise, returns EAGAIN if the 'sock' send buffer is full. |
644 | | * |
645 | | * This function is suitable for sending a reply to a request that was received |
646 | | * with sequence number 'nlmsg_seq'. Otherwise, use nl_sock_send() instead. */ |
647 | | int |
648 | | nl_sock_send_seq(struct nl_sock *sock, const struct ofpbuf *msg, |
649 | | uint32_t nlmsg_seq, bool wait) |
650 | 0 | { |
651 | 0 | return nl_sock_send__(sock, msg, nlmsg_seq, wait); |
652 | 0 | } |
653 | | |
654 | | static int |
655 | | nl_sock_recv__(struct nl_sock *sock, struct ofpbuf *buf, int *nsid, bool wait) |
656 | 0 | { |
657 | | /* We can't accurately predict the size of the data to be received. The |
658 | | * caller is supposed to have allocated enough space in 'buf' to handle the |
659 | | * "typical" case. To handle exceptions, we make available enough space in |
660 | | * 'tail' to allow Netlink messages to be up to 64 kB long (a reasonable |
661 | | * figure since that's the maximum length of a Netlink attribute). */ |
662 | 0 | struct nlmsghdr *nlmsghdr; |
663 | 0 | uint8_t tail[65536]; |
664 | 0 | struct iovec iov[2]; |
665 | 0 | struct msghdr msg; |
666 | 0 | uint8_t msgctrl[64]; |
667 | 0 | struct cmsghdr *cmsg; |
668 | 0 | ssize_t retval; |
669 | 0 | int *ptr; |
670 | 0 | int error; |
671 | |
|
672 | 0 | ovs_assert(buf->allocated >= sizeof *nlmsghdr); |
673 | 0 | ofpbuf_clear(buf); |
674 | |
|
675 | 0 | iov[0].iov_base = buf->base; |
676 | 0 | iov[0].iov_len = buf->allocated; |
677 | 0 | iov[1].iov_base = tail; |
678 | 0 | iov[1].iov_len = sizeof tail; |
679 | |
|
680 | 0 | memset(&msg, 0, sizeof msg); |
681 | 0 | msg.msg_iov = iov; |
682 | 0 | msg.msg_iovlen = 2; |
683 | 0 | msg.msg_control = msgctrl; |
684 | 0 | msg.msg_controllen = sizeof msgctrl; |
685 | | |
686 | | /* Receive a Netlink message from the kernel. |
687 | | * |
688 | | * This works around a kernel bug in which the kernel returns an error code |
689 | | * as if it were the number of bytes read. It doesn't actually modify |
690 | | * anything in the receive buffer in that case, so we can initialize the |
691 | | * Netlink header with an impossible message length and then, upon success, |
692 | | * check whether it changed. */ |
693 | 0 | nlmsghdr = buf->base; |
694 | 0 | do { |
695 | 0 | nlmsghdr->nlmsg_len = UINT32_MAX; |
696 | | #ifdef _WIN32 |
697 | | DWORD bytes; |
698 | | if (!DeviceIoControl(sock->handle, sock->read_ioctl, |
699 | | NULL, 0, tail, sizeof tail, &bytes, NULL)) { |
700 | | lost_communication(GetLastError()); |
701 | | VLOG_DBG_RL(&rl, "fatal driver failure in transact: %s", |
702 | | ovs_lasterror_to_string()); |
703 | | retval = -1; |
704 | | /* XXX: Map to a more appropriate error. */ |
705 | | errno = EINVAL; |
706 | | } else { |
707 | | retval = bytes; |
708 | | if (retval == 0) { |
709 | | retval = -1; |
710 | | errno = EAGAIN; |
711 | | } else { |
712 | | if (retval >= buf->allocated) { |
713 | | ofpbuf_reinit(buf, retval); |
714 | | nlmsghdr = buf->base; |
715 | | nlmsghdr->nlmsg_len = UINT32_MAX; |
716 | | } |
717 | | memcpy(buf->data, tail, retval); |
718 | | buf->size = retval; |
719 | | } |
720 | | } |
721 | | #else |
722 | 0 | retval = recvmsg(sock->fd, &msg, wait ? 0 : MSG_DONTWAIT); |
723 | 0 | #endif |
724 | 0 | error = (retval < 0 ? errno |
725 | 0 | : retval == 0 ? ECONNRESET /* not possible? */ |
726 | 0 | : nlmsghdr->nlmsg_len != UINT32_MAX ? 0 |
727 | 0 | : retval); |
728 | 0 | } while (error == EINTR); |
729 | 0 | if (error) { |
730 | 0 | if (error == ENOBUFS) { |
731 | | /* Socket receive buffer overflow dropped one or more messages that |
732 | | * the kernel tried to send to us. */ |
733 | 0 | COVERAGE_INC(netlink_overflow); |
734 | 0 | } |
735 | 0 | return error; |
736 | 0 | } |
737 | | |
738 | 0 | if (msg.msg_flags & MSG_TRUNC) { |
739 | 0 | VLOG_ERR_RL(&rl, "truncated message (longer than %"PRIuSIZE" bytes)", |
740 | 0 | sizeof tail); |
741 | 0 | return E2BIG; |
742 | 0 | } |
743 | | |
744 | 0 | if (retval < sizeof *nlmsghdr |
745 | 0 | || nlmsghdr->nlmsg_len < sizeof *nlmsghdr |
746 | 0 | || nlmsghdr->nlmsg_len > retval) { |
747 | 0 | VLOG_ERR_RL(&rl, "received invalid nlmsg (%"PRIuSIZE" bytes < %"PRIuSIZE")", |
748 | 0 | retval, sizeof *nlmsghdr); |
749 | 0 | return EPROTO; |
750 | 0 | } |
751 | 0 | #ifndef _WIN32 |
752 | 0 | buf->size = MIN(retval, buf->allocated); |
753 | 0 | if (retval > buf->allocated) { |
754 | 0 | COVERAGE_INC(netlink_recv_jumbo); |
755 | 0 | ofpbuf_put(buf, tail, retval - buf->allocated); |
756 | 0 | } |
757 | 0 | #endif |
758 | |
|
759 | 0 | if (nsid) { |
760 | | /* The network namespace id from which the message was sent comes |
761 | | * as ancillary data. For older kernels, this data is either not |
762 | | * available or it might be -1, so it falls back to local network |
763 | | * namespace (no id). Latest kernels return a valid ID only if |
764 | | * available or nothing. */ |
765 | 0 | netnsid_set_local(nsid); |
766 | 0 | #ifndef _WIN32 |
767 | 0 | cmsg = CMSG_FIRSTHDR(&msg); |
768 | 0 | while (cmsg != NULL) { |
769 | 0 | if (cmsg->cmsg_level == SOL_NETLINK |
770 | 0 | && cmsg->cmsg_type == NETLINK_LISTEN_ALL_NSID) { |
771 | 0 | ptr = ALIGNED_CAST(int *, CMSG_DATA(cmsg)); |
772 | 0 | netnsid_set(nsid, *ptr); |
773 | 0 | } |
774 | 0 | if (cmsg->cmsg_level == SOL_SOCKET |
775 | 0 | && cmsg->cmsg_type == SCM_RIGHTS) { |
776 | | /* This is unexpected and unwanted, close all fds */ |
777 | 0 | int nfds; |
778 | 0 | int i; |
779 | 0 | nfds = (cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) |
780 | 0 | / sizeof(int); |
781 | 0 | ptr = ALIGNED_CAST(int *, CMSG_DATA(cmsg)); |
782 | 0 | for (i = 0; i < nfds; i++) { |
783 | 0 | VLOG_ERR_RL(&rl, "closing unexpected received fd (%d).", |
784 | 0 | ptr[i]); |
785 | 0 | close(ptr[i]); |
786 | 0 | } |
787 | 0 | } |
788 | |
|
789 | 0 | cmsg = CMSG_NXTHDR(&msg, cmsg); |
790 | 0 | } |
791 | 0 | #endif |
792 | 0 | } |
793 | |
|
794 | 0 | log_nlmsg(__func__, 0, buf->data, buf->size, sock->protocol); |
795 | 0 | COVERAGE_INC(netlink_received); |
796 | |
|
797 | 0 | return 0; |
798 | 0 | } |
799 | | |
800 | | /* Tries to receive a Netlink message from the kernel on 'sock' into 'buf'. If |
801 | | * 'wait' is true, waits for a message to be ready. Otherwise, fails with |
802 | | * EAGAIN if the 'sock' receive buffer is empty. If 'nsid' is provided, the |
803 | | * network namespace id from which the message was sent will be provided. |
804 | | * |
805 | | * The caller must have initialized 'buf' with an allocation of at least |
806 | | * NLMSG_HDRLEN bytes. For best performance, the caller should allocate enough |
807 | | * space for a "typical" message. |
808 | | * |
809 | | * On success, returns 0 and replaces 'buf''s previous content by the received |
810 | | * message. This function expands 'buf''s allocated memory, as necessary, to |
811 | | * hold the actual size of the received message. |
812 | | * |
813 | | * On failure, returns a positive errno value and clears 'buf' to zero length. |
814 | | * 'buf' retains its previous memory allocation. |
815 | | * |
816 | | * Regardless of success or failure, this function resets 'buf''s headroom to |
817 | | * 0. */ |
818 | | int |
819 | | nl_sock_recv(struct nl_sock *sock, struct ofpbuf *buf, int *nsid, bool wait) |
820 | 0 | { |
821 | 0 | return nl_sock_recv__(sock, buf, nsid, wait); |
822 | 0 | } |
823 | | |
824 | | static void |
825 | | nl_sock_record_errors__(struct nl_transaction **transactions, size_t n, |
826 | | int error) |
827 | 0 | { |
828 | 0 | size_t i; |
829 | |
|
830 | 0 | for (i = 0; i < n; i++) { |
831 | 0 | struct nl_transaction *txn = transactions[i]; |
832 | |
|
833 | 0 | txn->error = error; |
834 | 0 | if (txn->reply) { |
835 | 0 | ofpbuf_clear(txn->reply); |
836 | 0 | } |
837 | 0 | } |
838 | 0 | } |
839 | | |
840 | | static int |
841 | | nl_sock_transact_multiple__(struct nl_sock *sock, |
842 | | struct nl_transaction **transactions, size_t n, |
843 | | size_t *done) |
844 | 0 | { |
845 | 0 | uint64_t tmp_reply_stub[1024 / 8]; |
846 | 0 | struct nl_transaction tmp_txn; |
847 | 0 | struct ofpbuf tmp_reply; |
848 | |
|
849 | 0 | uint32_t base_seq; |
850 | 0 | struct iovec iovs[MAX_IOVS]; |
851 | 0 | struct msghdr msg; |
852 | 0 | int error; |
853 | 0 | int i; |
854 | |
|
855 | 0 | base_seq = nl_sock_allocate_seq(sock, n); |
856 | 0 | *done = 0; |
857 | 0 | for (i = 0; i < n; i++) { |
858 | 0 | struct nl_transaction *txn = transactions[i]; |
859 | 0 | struct nlmsghdr *nlmsg = nl_msg_nlmsghdr(txn->request); |
860 | |
|
861 | 0 | nlmsg->nlmsg_len = txn->request->size; |
862 | 0 | nlmsg->nlmsg_seq = base_seq + i; |
863 | 0 | nlmsg->nlmsg_pid = sock->pid; |
864 | |
|
865 | 0 | iovs[i].iov_base = txn->request->data; |
866 | 0 | iovs[i].iov_len = txn->request->size; |
867 | 0 | } |
868 | |
|
869 | 0 | #ifndef _WIN32 |
870 | 0 | memset(&msg, 0, sizeof msg); |
871 | 0 | msg.msg_iov = iovs; |
872 | 0 | msg.msg_iovlen = n; |
873 | 0 | do { |
874 | 0 | error = sendmsg(sock->fd, &msg, 0) < 0 ? errno : 0; |
875 | 0 | } while (error == EINTR); |
876 | |
|
877 | 0 | for (i = 0; i < n; i++) { |
878 | 0 | struct nl_transaction *txn = transactions[i]; |
879 | |
|
880 | 0 | log_nlmsg(__func__, error, txn->request->data, |
881 | 0 | txn->request->size, sock->protocol); |
882 | 0 | } |
883 | 0 | if (!error) { |
884 | 0 | COVERAGE_ADD(netlink_sent, n); |
885 | 0 | } |
886 | |
|
887 | 0 | if (error) { |
888 | 0 | return error; |
889 | 0 | } |
890 | | |
891 | 0 | ofpbuf_use_stub(&tmp_reply, tmp_reply_stub, sizeof tmp_reply_stub); |
892 | 0 | tmp_txn.request = NULL; |
893 | 0 | tmp_txn.reply = &tmp_reply; |
894 | 0 | tmp_txn.error = 0; |
895 | 0 | while (n > 0) { |
896 | 0 | struct nl_transaction *buf_txn, *txn; |
897 | 0 | uint32_t seq; |
898 | | |
899 | | /* Find a transaction whose buffer we can use for receiving a reply. |
900 | | * If no such transaction is left, use tmp_txn. */ |
901 | 0 | buf_txn = &tmp_txn; |
902 | 0 | for (i = 0; i < n; i++) { |
903 | 0 | if (transactions[i]->reply) { |
904 | 0 | buf_txn = transactions[i]; |
905 | 0 | break; |
906 | 0 | } |
907 | 0 | } |
908 | | |
909 | | /* Receive a reply. */ |
910 | 0 | error = nl_sock_recv__(sock, buf_txn->reply, NULL, false); |
911 | 0 | if (error) { |
912 | 0 | if (error == EAGAIN) { |
913 | 0 | nl_sock_record_errors__(transactions, n, 0); |
914 | 0 | *done += n; |
915 | 0 | error = 0; |
916 | 0 | } |
917 | 0 | break; |
918 | 0 | } |
919 | | |
920 | | /* Match the reply up with a transaction. */ |
921 | 0 | seq = nl_msg_nlmsghdr(buf_txn->reply)->nlmsg_seq; |
922 | 0 | if (seq < base_seq || seq >= base_seq + n) { |
923 | 0 | VLOG_DBG_RL(&rl, "ignoring unexpected seq %#"PRIx32, seq); |
924 | 0 | continue; |
925 | 0 | } |
926 | 0 | i = seq - base_seq; |
927 | 0 | txn = transactions[i]; |
928 | |
|
929 | 0 | const char *err_msg = NULL; |
930 | | /* Fill in the results for 'txn'. */ |
931 | 0 | if (nl_msg_nlmsgerr(buf_txn->reply, &txn->error, &err_msg)) { |
932 | 0 | if (txn->error) { |
933 | 0 | VLOG_DBG_RL(&rl, "received NAK error=%d - %s", |
934 | 0 | txn->error, |
935 | 0 | err_msg ? err_msg : ovs_strerror(txn->error)); |
936 | 0 | } |
937 | 0 | if (txn->reply) { |
938 | 0 | ofpbuf_clear(txn->reply); |
939 | 0 | } |
940 | 0 | } else { |
941 | 0 | txn->error = 0; |
942 | 0 | if (txn->reply && txn != buf_txn) { |
943 | | /* Swap buffers. */ |
944 | 0 | struct ofpbuf *reply = buf_txn->reply; |
945 | 0 | buf_txn->reply = txn->reply; |
946 | 0 | txn->reply = reply; |
947 | 0 | } |
948 | 0 | } |
949 | | |
950 | | /* Fill in the results for transactions before 'txn'. (We have to do |
951 | | * this after the results for 'txn' itself because of the buffer swap |
952 | | * above.) */ |
953 | 0 | nl_sock_record_errors__(transactions, i, 0); |
954 | | |
955 | | /* Advance. */ |
956 | 0 | *done += i + 1; |
957 | 0 | transactions += i + 1; |
958 | 0 | n -= i + 1; |
959 | 0 | base_seq += i + 1; |
960 | 0 | } |
961 | 0 | ofpbuf_uninit(&tmp_reply); |
962 | | #else |
963 | | error = 0; |
964 | | uint8_t reply_buf[65536]; |
965 | | for (i = 0; i < n; i++) { |
966 | | DWORD reply_len; |
967 | | bool ret; |
968 | | struct nl_transaction *txn = transactions[i]; |
969 | | struct nlmsghdr *request_nlmsg, *reply_nlmsg; |
970 | | |
971 | | ret = DeviceIoControl(sock->handle, OVS_IOCTL_TRANSACT, |
972 | | txn->request->data, |
973 | | txn->request->size, |
974 | | reply_buf, sizeof reply_buf, |
975 | | &reply_len, NULL); |
976 | | |
977 | | if (ret && reply_len == 0) { |
978 | | /* |
979 | | * The current transaction did not produce any data to read and that |
980 | | * is not an error as such. Continue with the remainder of the |
981 | | * transactions. |
982 | | */ |
983 | | txn->error = 0; |
984 | | if (txn->reply) { |
985 | | ofpbuf_clear(txn->reply); |
986 | | } |
987 | | } else if (!ret) { |
988 | | /* XXX: Map to a more appropriate error. */ |
989 | | lost_communication(GetLastError()); |
990 | | error = EINVAL; |
991 | | VLOG_DBG_RL(&rl, "fatal driver failure: %s", |
992 | | ovs_lasterror_to_string()); |
993 | | break; |
994 | | } |
995 | | |
996 | | if (reply_len != 0) { |
997 | | request_nlmsg = nl_msg_nlmsghdr(txn->request); |
998 | | |
999 | | if (reply_len < sizeof *reply_nlmsg) { |
1000 | | nl_sock_record_errors__(transactions, n, 0); |
1001 | | VLOG_DBG_RL(&rl, "insufficient length of reply %#"PRIu32 |
1002 | | " for seq: %#"PRIx32, reply_len, request_nlmsg->nlmsg_seq); |
1003 | | break; |
1004 | | } |
1005 | | |
1006 | | /* Validate the sequence number in the reply. */ |
1007 | | reply_nlmsg = (struct nlmsghdr *)reply_buf; |
1008 | | |
1009 | | if (request_nlmsg->nlmsg_seq != reply_nlmsg->nlmsg_seq) { |
1010 | | ovs_assert(request_nlmsg->nlmsg_seq == reply_nlmsg->nlmsg_seq); |
1011 | | VLOG_DBG_RL(&rl, "mismatched seq request %#"PRIx32 |
1012 | | ", reply %#"PRIx32, request_nlmsg->nlmsg_seq, |
1013 | | reply_nlmsg->nlmsg_seq); |
1014 | | break; |
1015 | | } |
1016 | | |
1017 | | /* Handle errors embedded within the netlink message. */ |
1018 | | ofpbuf_use_stub(&tmp_reply, reply_buf, sizeof reply_buf); |
1019 | | tmp_reply.size = sizeof reply_buf; |
1020 | | if (nl_msg_nlmsgerr(&tmp_reply, &txn->error, NULL)) { |
1021 | | if (txn->reply) { |
1022 | | ofpbuf_clear(txn->reply); |
1023 | | } |
1024 | | if (txn->error) { |
1025 | | VLOG_DBG_RL(&rl, "received NAK error=%d (%s)", |
1026 | | error, ovs_strerror(txn->error)); |
1027 | | } |
1028 | | } else { |
1029 | | txn->error = 0; |
1030 | | if (txn->reply) { |
1031 | | /* Copy the reply to the buffer specified by the caller. */ |
1032 | | if (reply_len > txn->reply->allocated) { |
1033 | | ofpbuf_reinit(txn->reply, reply_len); |
1034 | | } |
1035 | | memcpy(txn->reply->data, reply_buf, reply_len); |
1036 | | txn->reply->size = reply_len; |
1037 | | } |
1038 | | } |
1039 | | ofpbuf_uninit(&tmp_reply); |
1040 | | } |
1041 | | |
1042 | | /* Count the number of successful transactions. */ |
1043 | | (*done)++; |
1044 | | |
1045 | | } |
1046 | | |
1047 | | if (!error) { |
1048 | | COVERAGE_ADD(netlink_sent, n); |
1049 | | } |
1050 | | #endif |
1051 | |
|
1052 | 0 | return error; |
1053 | 0 | } |
1054 | | |
1055 | | static void |
1056 | | nl_sock_transact_multiple(struct nl_sock *sock, |
1057 | | struct nl_transaction **transactions, size_t n) |
1058 | 0 | { |
1059 | 0 | int max_batch_count; |
1060 | 0 | int error; |
1061 | |
|
1062 | 0 | if (!n) { |
1063 | 0 | return; |
1064 | 0 | } |
1065 | | |
1066 | | /* In theory, every request could have a 64 kB reply. But the default and |
1067 | | * maximum socket rcvbuf size with typical Dom0 memory sizes both tend to |
1068 | | * be a bit below 128 kB, so that would only allow a single message in a |
1069 | | * "batch". So we assume that replies average (at most) 4 kB, which allows |
1070 | | * a good deal of batching. |
1071 | | * |
1072 | | * In practice, most of the requests that we batch either have no reply at |
1073 | | * all or a brief reply. */ |
1074 | 0 | max_batch_count = MAX(sock->rcvbuf / 4096, 1); |
1075 | 0 | max_batch_count = MIN(max_batch_count, max_iovs); |
1076 | |
|
1077 | 0 | while (n > 0) { |
1078 | 0 | size_t count, bytes; |
1079 | 0 | size_t done; |
1080 | | |
1081 | | /* Batch up to 'max_batch_count' transactions. But cap it at about a |
1082 | | * page of requests total because big skbuffs are expensive to |
1083 | | * allocate in the kernel. */ |
1084 | | #if defined(PAGESIZE) |
1085 | | enum { MAX_BATCH_BYTES = MAX(1, PAGESIZE - 512) }; |
1086 | | #else |
1087 | 0 | enum { MAX_BATCH_BYTES = 4096 - 512 }; |
1088 | 0 | #endif |
1089 | 0 | bytes = transactions[0]->request->size; |
1090 | 0 | for (count = 1; count < n && count < max_batch_count; count++) { |
1091 | 0 | if (bytes + transactions[count]->request->size > MAX_BATCH_BYTES) { |
1092 | 0 | break; |
1093 | 0 | } |
1094 | 0 | bytes += transactions[count]->request->size; |
1095 | 0 | } |
1096 | |
|
1097 | 0 | error = nl_sock_transact_multiple__(sock, transactions, count, &done); |
1098 | 0 | transactions += done; |
1099 | 0 | n -= done; |
1100 | |
|
1101 | 0 | if (error == ENOBUFS) { |
1102 | 0 | VLOG_DBG_RL(&rl, "receive buffer overflow, resending request"); |
1103 | 0 | } else if (error) { |
1104 | 0 | VLOG_ERR_RL(&rl, "transaction error (%s)", ovs_strerror(error)); |
1105 | 0 | nl_sock_record_errors__(transactions, n, error); |
1106 | 0 | if (error != EAGAIN) { |
1107 | | /* A fatal error has occurred. Abort the rest of |
1108 | | * transactions. */ |
1109 | 0 | break; |
1110 | 0 | } |
1111 | 0 | } |
1112 | 0 | } |
1113 | 0 | } |
1114 | | |
1115 | | static int |
1116 | | nl_sock_transact(struct nl_sock *sock, const struct ofpbuf *request, |
1117 | | struct ofpbuf **replyp) |
1118 | 0 | { |
1119 | 0 | struct nl_transaction *transactionp; |
1120 | 0 | struct nl_transaction transaction; |
1121 | |
|
1122 | 0 | transaction.request = CONST_CAST(struct ofpbuf *, request); |
1123 | 0 | transaction.reply = replyp ? ofpbuf_new(1024) : NULL; |
1124 | 0 | transactionp = &transaction; |
1125 | |
|
1126 | 0 | nl_sock_transact_multiple(sock, &transactionp, 1); |
1127 | |
|
1128 | 0 | if (replyp) { |
1129 | 0 | if (transaction.error) { |
1130 | 0 | ofpbuf_delete(transaction.reply); |
1131 | 0 | *replyp = NULL; |
1132 | 0 | } else { |
1133 | 0 | *replyp = transaction.reply; |
1134 | 0 | } |
1135 | 0 | } |
1136 | |
|
1137 | 0 | return transaction.error; |
1138 | 0 | } |
1139 | | |
1140 | | /* Drain all the messages currently in 'sock''s receive queue. */ |
1141 | | int |
1142 | | nl_sock_drain(struct nl_sock *sock) |
1143 | 0 | { |
1144 | | #ifdef _WIN32 |
1145 | | return 0; |
1146 | | #else |
1147 | 0 | return drain_rcvbuf(sock->fd); |
1148 | 0 | #endif |
1149 | 0 | } |
1150 | | |
1151 | | /* Starts a Netlink "dump" operation, by sending 'request' to the kernel on a |
1152 | | * Netlink socket created with the given 'protocol', and initializes 'dump' to |
1153 | | * reflect the state of the operation. |
1154 | | * |
1155 | | * 'request' must contain a Netlink message. Before sending the message, |
1156 | | * nlmsg_len will be finalized to match request->size, and nlmsg_pid will be |
1157 | | * set to the Netlink socket's pid. NLM_F_DUMP and NLM_F_ACK will be set in |
1158 | | * nlmsg_flags. |
1159 | | * |
1160 | | * The design of this Netlink socket library ensures that the dump is reliable. |
1161 | | * |
1162 | | * This function provides no status indication. nl_dump_done() provides an |
1163 | | * error status for the entire dump operation. |
1164 | | * |
1165 | | * The caller must eventually destroy 'request'. |
1166 | | */ |
1167 | | void |
1168 | | nl_dump_start(struct nl_dump *dump, int protocol, const struct ofpbuf *request) |
1169 | 0 | { |
1170 | 0 | nl_msg_nlmsghdr(request)->nlmsg_flags |= NLM_F_DUMP | NLM_F_ACK; |
1171 | |
|
1172 | 0 | ovs_mutex_init(&dump->mutex); |
1173 | 0 | ovs_mutex_lock(&dump->mutex); |
1174 | 0 | dump->status = nl_pool_alloc(protocol, &dump->sock); |
1175 | 0 | if (!dump->status) { |
1176 | 0 | dump->status = nl_sock_send__(dump->sock, request, |
1177 | 0 | nl_sock_allocate_seq(dump->sock, 1), |
1178 | 0 | true); |
1179 | 0 | } |
1180 | 0 | dump->nl_seq = nl_msg_nlmsghdr(request)->nlmsg_seq; |
1181 | 0 | ovs_mutex_unlock(&dump->mutex); |
1182 | 0 | } |
1183 | | |
1184 | | static int |
1185 | | nl_dump_refill(struct nl_dump *dump, struct ofpbuf *buffer) |
1186 | | OVS_REQUIRES(dump->mutex) |
1187 | 0 | { |
1188 | 0 | struct nlmsghdr *nlmsghdr; |
1189 | 0 | int error; |
1190 | |
|
1191 | 0 | while (!buffer->size) { |
1192 | 0 | error = nl_sock_recv__(dump->sock, buffer, NULL, false); |
1193 | 0 | if (error) { |
1194 | | /* The kernel never blocks providing the results of a dump, so |
1195 | | * error == EAGAIN means that we've read the whole thing, and |
1196 | | * therefore transform it into EOF. (The kernel always provides |
1197 | | * NLMSG_DONE as a sentinel. Some other thread must have received |
1198 | | * that already but not yet signaled it in 'status'.) |
1199 | | * |
1200 | | * Any other error is just an error. */ |
1201 | 0 | return error == EAGAIN ? EOF : error; |
1202 | 0 | } |
1203 | | |
1204 | 0 | nlmsghdr = nl_msg_nlmsghdr(buffer); |
1205 | 0 | if (dump->nl_seq != nlmsghdr->nlmsg_seq) { |
1206 | 0 | VLOG_DBG_RL(&rl, "ignoring seq %#"PRIx32" != expected %#"PRIx32, |
1207 | 0 | nlmsghdr->nlmsg_seq, dump->nl_seq); |
1208 | 0 | ofpbuf_clear(buffer); |
1209 | 0 | } |
1210 | 0 | } |
1211 | | |
1212 | 0 | if (nl_msg_nlmsgerr(buffer, &error, NULL) && error) { |
1213 | 0 | VLOG_INFO_RL(&rl, "netlink dump request error (%s)", |
1214 | 0 | ovs_strerror(error)); |
1215 | 0 | ofpbuf_clear(buffer); |
1216 | 0 | return error; |
1217 | 0 | } |
1218 | | |
1219 | 0 | return 0; |
1220 | 0 | } |
1221 | | |
1222 | | static int |
1223 | | nl_dump_next__(struct ofpbuf *reply, struct ofpbuf *buffer) |
1224 | 0 | { |
1225 | 0 | struct nlmsghdr *nlmsghdr = nl_msg_next(buffer, reply); |
1226 | 0 | if (!nlmsghdr) { |
1227 | 0 | VLOG_WARN_RL(&rl, "netlink dump contains message fragment"); |
1228 | 0 | return EPROTO; |
1229 | 0 | } else if (nlmsghdr->nlmsg_type == NLMSG_DONE) { |
1230 | 0 | return EOF; |
1231 | 0 | } else { |
1232 | 0 | return 0; |
1233 | 0 | } |
1234 | 0 | } |
1235 | | |
1236 | | /* Attempts to retrieve another reply from 'dump' into 'buffer'. 'dump' must |
1237 | | * have been initialized with nl_dump_start(), and 'buffer' must have been |
1238 | | * initialized. 'buffer' should be at least NL_DUMP_BUFSIZE bytes long. |
1239 | | * |
1240 | | * If successful, returns true and points 'reply->data' and |
1241 | | * 'reply->size' to the message that was retrieved. The caller must not |
1242 | | * modify 'reply' (because it points within 'buffer', which will be used by |
1243 | | * future calls to this function). |
1244 | | * |
1245 | | * On failure, returns false and sets 'reply->data' to NULL and |
1246 | | * 'reply->size' to 0. Failure might indicate an actual error or merely |
1247 | | * the end of replies. An error status for the entire dump operation is |
1248 | | * provided when it is completed by calling nl_dump_done(). |
1249 | | * |
1250 | | * Multiple threads may call this function, passing the same nl_dump, however |
1251 | | * each must provide independent buffers. This function may cache multiple |
1252 | | * replies in the buffer, and these will be processed before more replies are |
1253 | | * fetched. When this function returns false, other threads may continue to |
1254 | | * process replies in their buffers, but they will not fetch more replies. |
1255 | | */ |
1256 | | bool |
1257 | | nl_dump_next(struct nl_dump *dump, struct ofpbuf *reply, struct ofpbuf *buffer) |
1258 | 0 | { |
1259 | 0 | int retval = 0; |
1260 | | |
1261 | | /* If the buffer is empty, refill it. |
1262 | | * |
1263 | | * If the buffer is not empty, we don't check the dump's status. |
1264 | | * Otherwise, we could end up skipping some of the dump results if thread A |
1265 | | * hits EOF while thread B is in the midst of processing a batch. */ |
1266 | 0 | if (!buffer->size) { |
1267 | 0 | ovs_mutex_lock(&dump->mutex); |
1268 | 0 | if (!dump->status) { |
1269 | | /* Take the mutex here to avoid an in-kernel race. If two threads |
1270 | | * try to read from a Netlink dump socket at once, then the socket |
1271 | | * error can be set to EINVAL, which will be encountered on the |
1272 | | * next recv on that socket, which could be anywhere due to the way |
1273 | | * that we pool Netlink sockets. Serializing the recv calls avoids |
1274 | | * the issue. */ |
1275 | 0 | dump->status = nl_dump_refill(dump, buffer); |
1276 | 0 | } |
1277 | 0 | retval = dump->status; |
1278 | 0 | ovs_mutex_unlock(&dump->mutex); |
1279 | 0 | } |
1280 | | |
1281 | | /* Fetch the next message from the buffer. */ |
1282 | 0 | if (!retval) { |
1283 | 0 | retval = nl_dump_next__(reply, buffer); |
1284 | 0 | if (retval) { |
1285 | | /* Record 'retval' as the dump status, but don't overwrite an error |
1286 | | * with EOF. */ |
1287 | 0 | ovs_mutex_lock(&dump->mutex); |
1288 | 0 | if (dump->status <= 0) { |
1289 | 0 | dump->status = retval; |
1290 | 0 | } |
1291 | 0 | ovs_mutex_unlock(&dump->mutex); |
1292 | 0 | } |
1293 | 0 | } |
1294 | |
|
1295 | 0 | if (retval) { |
1296 | 0 | reply->data = NULL; |
1297 | 0 | reply->size = 0; |
1298 | 0 | } |
1299 | 0 | return !retval; |
1300 | 0 | } |
1301 | | |
1302 | | /* Completes Netlink dump operation 'dump', which must have been initialized |
1303 | | * with nl_dump_start(). Returns 0 if the dump operation was error-free, |
1304 | | * otherwise a positive errno value describing the problem. */ |
1305 | | int |
1306 | | nl_dump_done(struct nl_dump *dump) |
1307 | 0 | { |
1308 | 0 | int status; |
1309 | |
|
1310 | 0 | ovs_mutex_lock(&dump->mutex); |
1311 | 0 | status = dump->status; |
1312 | 0 | ovs_mutex_unlock(&dump->mutex); |
1313 | | |
1314 | | /* Drain any remaining messages that the client didn't read. Otherwise the |
1315 | | * kernel will continue to queue them up and waste buffer space. |
1316 | | * |
1317 | | * XXX We could just destroy and discard the socket in this case. */ |
1318 | 0 | if (!status) { |
1319 | 0 | uint64_t tmp_reply_stub[NL_DUMP_BUFSIZE / 8]; |
1320 | 0 | struct ofpbuf reply, buf; |
1321 | |
|
1322 | 0 | ofpbuf_use_stub(&buf, tmp_reply_stub, sizeof tmp_reply_stub); |
1323 | 0 | while (nl_dump_next(dump, &reply, &buf)) { |
1324 | | /* Nothing to do. */ |
1325 | 0 | } |
1326 | 0 | ofpbuf_uninit(&buf); |
1327 | |
|
1328 | 0 | ovs_mutex_lock(&dump->mutex); |
1329 | 0 | status = dump->status; |
1330 | 0 | ovs_mutex_unlock(&dump->mutex); |
1331 | 0 | ovs_assert(status); |
1332 | 0 | } |
1333 | |
|
1334 | 0 | nl_pool_release(dump->sock); |
1335 | 0 | ovs_mutex_destroy(&dump->mutex); |
1336 | |
|
1337 | 0 | return status == EOF ? 0 : status; |
1338 | 0 | } |
1339 | | |
1340 | | #ifdef _WIN32 |
1341 | | /* Pend an I/O request in the driver. The driver completes the I/O whenever |
1342 | | * an event or a packet is ready to be read. Once the I/O is completed |
1343 | | * the overlapped structure event associated with the pending I/O will be set |
1344 | | */ |
1345 | | static int |
1346 | | pend_io_request(struct nl_sock *sock) |
1347 | | { |
1348 | | struct ofpbuf request; |
1349 | | uint64_t request_stub[128]; |
1350 | | struct ovs_header *ovs_header; |
1351 | | struct nlmsghdr *nlmsg; |
1352 | | uint32_t seq; |
1353 | | int retval = 0; |
1354 | | int error; |
1355 | | DWORD bytes; |
1356 | | OVERLAPPED *overlapped = CONST_CAST(OVERLAPPED *, &sock->overlapped); |
1357 | | uint16_t cmd = OVS_CTRL_CMD_WIN_PEND_PACKET_REQ; |
1358 | | |
1359 | | ovs_assert(sock->read_ioctl == OVS_IOCTL_READ_PACKET || |
1360 | | sock->read_ioctl == OVS_IOCTL_READ_EVENT); |
1361 | | if (sock->read_ioctl == OVS_IOCTL_READ_EVENT) { |
1362 | | cmd = OVS_CTRL_CMD_WIN_PEND_REQ; |
1363 | | } |
1364 | | |
1365 | | int ovs_msg_size = sizeof (struct nlmsghdr) + sizeof (struct genlmsghdr) + |
1366 | | sizeof (struct ovs_header); |
1367 | | |
1368 | | ofpbuf_use_stub(&request, request_stub, sizeof request_stub); |
1369 | | |
1370 | | seq = nl_sock_allocate_seq(sock, 1); |
1371 | | nl_msg_put_genlmsghdr(&request, 0, OVS_WIN_NL_CTRL_FAMILY_ID, 0, |
1372 | | cmd, OVS_WIN_CONTROL_VERSION); |
1373 | | nlmsg = nl_msg_nlmsghdr(&request); |
1374 | | nlmsg->nlmsg_seq = seq; |
1375 | | nlmsg->nlmsg_pid = sock->pid; |
1376 | | |
1377 | | ovs_header = ofpbuf_put_uninit(&request, sizeof *ovs_header); |
1378 | | ovs_header->dp_ifindex = 0; |
1379 | | nlmsg->nlmsg_len = request.size; |
1380 | | |
1381 | | if (!DeviceIoControl(sock->handle, OVS_IOCTL_WRITE, |
1382 | | request.data, request.size, |
1383 | | NULL, 0, &bytes, overlapped)) { |
1384 | | error = GetLastError(); |
1385 | | /* Check if the I/O got pended */ |
1386 | | if (error != ERROR_IO_INCOMPLETE && error != ERROR_IO_PENDING) { |
1387 | | lost_communication(error); |
1388 | | VLOG_ERR("nl_sock_wait failed - %s\n", ovs_format_message(error)); |
1389 | | retval = EINVAL; |
1390 | | } |
1391 | | } else { |
1392 | | retval = EAGAIN; |
1393 | | } |
1394 | | |
1395 | | done: |
1396 | | ofpbuf_uninit(&request); |
1397 | | return retval; |
1398 | | } |
1399 | | #endif /* _WIN32 */ |
1400 | | |
1401 | | /* Causes poll_block() to wake up when any of the specified 'events' (which is |
1402 | | * a OR'd combination of POLLIN, POLLOUT, etc.) occur on 'sock'. |
1403 | | * On Windows, 'sock' is not treated as const, and may be modified. */ |
1404 | | void |
1405 | | nl_sock_wait(const struct nl_sock *sock, short int events) |
1406 | 0 | { |
1407 | | #ifdef _WIN32 |
1408 | | if (sock->overlapped.Internal != STATUS_PENDING) { |
1409 | | int ret = pend_io_request(CONST_CAST(struct nl_sock *, sock)); |
1410 | | if (ret == 0) { |
1411 | | poll_wevent_wait(sock->overlapped.hEvent); |
1412 | | } else { |
1413 | | poll_immediate_wake(); |
1414 | | } |
1415 | | } else { |
1416 | | poll_wevent_wait(sock->overlapped.hEvent); |
1417 | | } |
1418 | | #else |
1419 | 0 | poll_fd_wait(sock->fd, events); |
1420 | 0 | #endif |
1421 | 0 | } |
1422 | | |
1423 | | #ifndef _WIN32 |
1424 | | /* Returns the underlying fd for 'sock', for use in "poll()"-like operations |
1425 | | * that can't use nl_sock_wait(). |
1426 | | * |
1427 | | * It's a little tricky to use the returned fd correctly, because nl_sock does |
1428 | | * "copy on write" to allow a single nl_sock to be used for notifications, |
1429 | | * transactions, and dumps. If 'sock' is used only for notifications and |
1430 | | * transactions (and never for dump) then the usage is safe. */ |
1431 | | int |
1432 | | nl_sock_fd(const struct nl_sock *sock) |
1433 | 0 | { |
1434 | 0 | return sock->fd; |
1435 | 0 | } |
1436 | | #endif |
1437 | | |
1438 | | /* Returns the PID associated with this socket. */ |
1439 | | uint32_t |
1440 | | nl_sock_pid(const struct nl_sock *sock) |
1441 | 0 | { |
1442 | 0 | return sock->pid; |
1443 | 0 | } |
1444 | | |
1445 | | /* Miscellaneous. */ |
1446 | | |
1447 | | struct genl_family { |
1448 | | struct hmap_node hmap_node; |
1449 | | uint16_t id; |
1450 | | char *name; |
1451 | | }; |
1452 | | |
1453 | | static struct hmap genl_families = HMAP_INITIALIZER(&genl_families); |
1454 | | |
1455 | | static const struct nl_policy family_policy[CTRL_ATTR_MAX + 1] = { |
1456 | | [CTRL_ATTR_FAMILY_ID] = {.type = NL_A_U16}, |
1457 | | [CTRL_ATTR_MCAST_GROUPS] = {.type = NL_A_NESTED, .optional = true}, |
1458 | | }; |
1459 | | |
1460 | | static struct genl_family * |
1461 | | find_genl_family_by_id(uint16_t id) |
1462 | 0 | { |
1463 | 0 | struct genl_family *family; |
1464 | |
|
1465 | 0 | HMAP_FOR_EACH_IN_BUCKET (family, hmap_node, hash_int(id, 0), |
1466 | 0 | &genl_families) { |
1467 | 0 | if (family->id == id) { |
1468 | 0 | return family; |
1469 | 0 | } |
1470 | 0 | } |
1471 | 0 | return NULL; |
1472 | 0 | } |
1473 | | |
1474 | | static void |
1475 | | define_genl_family(uint16_t id, const char *name) |
1476 | 0 | { |
1477 | 0 | struct genl_family *family = find_genl_family_by_id(id); |
1478 | |
|
1479 | 0 | if (family) { |
1480 | 0 | if (!strcmp(family->name, name)) { |
1481 | 0 | return; |
1482 | 0 | } |
1483 | 0 | free(family->name); |
1484 | 0 | } else { |
1485 | 0 | family = xmalloc(sizeof *family); |
1486 | 0 | family->id = id; |
1487 | 0 | hmap_insert(&genl_families, &family->hmap_node, hash_int(id, 0)); |
1488 | 0 | } |
1489 | 0 | family->name = xstrdup(name); |
1490 | 0 | } |
1491 | | |
1492 | | static const char * |
1493 | | genl_family_to_name(uint16_t id) |
1494 | 0 | { |
1495 | 0 | if (id == GENL_ID_CTRL) { |
1496 | 0 | return "control"; |
1497 | 0 | } else { |
1498 | 0 | struct genl_family *family = find_genl_family_by_id(id); |
1499 | 0 | return family ? family->name : "unknown"; |
1500 | 0 | } |
1501 | 0 | } |
1502 | | |
1503 | | #ifndef _WIN32 |
1504 | | static int |
1505 | | do_lookup_genl_family(const char *name, struct nlattr **attrs, |
1506 | | struct ofpbuf **replyp) |
1507 | 0 | { |
1508 | 0 | struct nl_sock *sock; |
1509 | 0 | struct ofpbuf request, *reply; |
1510 | 0 | int error; |
1511 | |
|
1512 | 0 | *replyp = NULL; |
1513 | 0 | error = nl_sock_create(NETLINK_GENERIC, &sock); |
1514 | 0 | if (error) { |
1515 | 0 | return error; |
1516 | 0 | } |
1517 | | |
1518 | 0 | ofpbuf_init(&request, 0); |
1519 | 0 | nl_msg_put_genlmsghdr(&request, 0, GENL_ID_CTRL, NLM_F_REQUEST, |
1520 | 0 | CTRL_CMD_GETFAMILY, 1); |
1521 | 0 | nl_msg_put_string(&request, CTRL_ATTR_FAMILY_NAME, name); |
1522 | 0 | error = nl_sock_transact(sock, &request, &reply); |
1523 | 0 | ofpbuf_uninit(&request); |
1524 | 0 | if (error) { |
1525 | 0 | nl_sock_destroy(sock); |
1526 | 0 | return error; |
1527 | 0 | } |
1528 | | |
1529 | 0 | if (!nl_policy_parse(reply, NLMSG_HDRLEN + GENL_HDRLEN, |
1530 | 0 | family_policy, attrs, ARRAY_SIZE(family_policy)) |
1531 | 0 | || nl_attr_get_u16(attrs[CTRL_ATTR_FAMILY_ID]) == 0) { |
1532 | 0 | nl_sock_destroy(sock); |
1533 | 0 | ofpbuf_delete(reply); |
1534 | 0 | return EPROTO; |
1535 | 0 | } |
1536 | | |
1537 | 0 | nl_sock_destroy(sock); |
1538 | 0 | *replyp = reply; |
1539 | 0 | return 0; |
1540 | 0 | } |
1541 | | #else |
1542 | | static int |
1543 | | do_lookup_genl_family(const char *name, struct nlattr **attrs, |
1544 | | struct ofpbuf **replyp) |
1545 | | { |
1546 | | struct nlmsghdr *nlmsg; |
1547 | | struct ofpbuf *reply; |
1548 | | int error; |
1549 | | uint16_t family_id; |
1550 | | const char *family_name; |
1551 | | uint32_t family_version; |
1552 | | uint32_t family_attrmax; |
1553 | | uint32_t mcgrp_id = OVS_WIN_NL_INVALID_MCGRP_ID; |
1554 | | const char *mcgrp_name = NULL; |
1555 | | |
1556 | | *replyp = NULL; |
1557 | | reply = ofpbuf_new(1024); |
1558 | | |
1559 | | /* CTRL_ATTR_MCAST_GROUPS is supported only for VPORT family. */ |
1560 | | if (!strcmp(name, OVS_WIN_CONTROL_FAMILY)) { |
1561 | | family_id = OVS_WIN_NL_CTRL_FAMILY_ID; |
1562 | | family_name = OVS_WIN_CONTROL_FAMILY; |
1563 | | family_version = OVS_WIN_CONTROL_VERSION; |
1564 | | family_attrmax = OVS_WIN_CONTROL_ATTR_MAX; |
1565 | | } else if (!strcmp(name, OVS_DATAPATH_FAMILY)) { |
1566 | | family_id = OVS_WIN_NL_DATAPATH_FAMILY_ID; |
1567 | | family_name = OVS_DATAPATH_FAMILY; |
1568 | | family_version = OVS_DATAPATH_VERSION; |
1569 | | family_attrmax = OVS_DP_ATTR_MAX; |
1570 | | } else if (!strcmp(name, OVS_PACKET_FAMILY)) { |
1571 | | family_id = OVS_WIN_NL_PACKET_FAMILY_ID; |
1572 | | family_name = OVS_PACKET_FAMILY; |
1573 | | family_version = OVS_PACKET_VERSION; |
1574 | | family_attrmax = OVS_PACKET_ATTR_MAX; |
1575 | | } else if (!strcmp(name, OVS_VPORT_FAMILY)) { |
1576 | | family_id = OVS_WIN_NL_VPORT_FAMILY_ID; |
1577 | | family_name = OVS_VPORT_FAMILY; |
1578 | | family_version = OVS_VPORT_VERSION; |
1579 | | family_attrmax = OVS_VPORT_ATTR_MAX; |
1580 | | mcgrp_id = OVS_WIN_NL_VPORT_MCGRP_ID; |
1581 | | mcgrp_name = OVS_VPORT_MCGROUP; |
1582 | | } else if (!strcmp(name, OVS_FLOW_FAMILY)) { |
1583 | | family_id = OVS_WIN_NL_FLOW_FAMILY_ID; |
1584 | | family_name = OVS_FLOW_FAMILY; |
1585 | | family_version = OVS_FLOW_VERSION; |
1586 | | family_attrmax = OVS_FLOW_ATTR_MAX; |
1587 | | } else if (!strcmp(name, OVS_METER_FAMILY)) { |
1588 | | family_id = OVS_WIN_NL_METER_FAMILY_ID; |
1589 | | family_name = OVS_METER_FAMILY; |
1590 | | family_version = OVS_METER_VERSION; |
1591 | | family_attrmax = __OVS_METER_ATTR_MAX; |
1592 | | } else if (!strcmp(name, OVS_WIN_NETDEV_FAMILY)) { |
1593 | | family_id = OVS_WIN_NL_NETDEV_FAMILY_ID; |
1594 | | family_name = OVS_WIN_NETDEV_FAMILY; |
1595 | | family_version = OVS_WIN_NETDEV_VERSION; |
1596 | | family_attrmax = OVS_WIN_NETDEV_ATTR_MAX; |
1597 | | } else if (!strcmp(name, OVS_CT_LIMIT_FAMILY)) { |
1598 | | family_id = OVS_WIN_NL_CTLIMIT_FAMILY_ID; |
1599 | | family_name = OVS_CT_LIMIT_FAMILY; |
1600 | | family_version = OVS_CT_LIMIT_VERSION; |
1601 | | family_attrmax = OVS_CT_LIMIT_ATTR_MAX; |
1602 | | } else { |
1603 | | ofpbuf_delete(reply); |
1604 | | return EINVAL; |
1605 | | } |
1606 | | |
1607 | | nl_msg_put_genlmsghdr(reply, 0, GENL_ID_CTRL, 0, |
1608 | | CTRL_CMD_NEWFAMILY, family_version); |
1609 | | /* CTRL_ATTR_HDRSIZE and CTRL_ATTR_OPS are not populated, but the |
1610 | | * callers do not seem to need them. */ |
1611 | | nl_msg_put_u16(reply, CTRL_ATTR_FAMILY_ID, family_id); |
1612 | | nl_msg_put_string(reply, CTRL_ATTR_FAMILY_NAME, family_name); |
1613 | | nl_msg_put_u32(reply, CTRL_ATTR_VERSION, family_version); |
1614 | | nl_msg_put_u32(reply, CTRL_ATTR_MAXATTR, family_attrmax); |
1615 | | |
1616 | | if (mcgrp_id != OVS_WIN_NL_INVALID_MCGRP_ID) { |
1617 | | size_t mcgrp_ofs1 = nl_msg_start_nested(reply, CTRL_ATTR_MCAST_GROUPS); |
1618 | | size_t mcgrp_ofs2= nl_msg_start_nested(reply, |
1619 | | OVS_WIN_NL_VPORT_MCGRP_ID - OVS_WIN_NL_MCGRP_START_ID); |
1620 | | nl_msg_put_u32(reply, CTRL_ATTR_MCAST_GRP_ID, mcgrp_id); |
1621 | | ovs_assert(mcgrp_name != NULL); |
1622 | | nl_msg_put_string(reply, CTRL_ATTR_MCAST_GRP_NAME, mcgrp_name); |
1623 | | nl_msg_end_nested(reply, mcgrp_ofs2); |
1624 | | nl_msg_end_nested(reply, mcgrp_ofs1); |
1625 | | } |
1626 | | |
1627 | | /* Set the total length of the netlink message. */ |
1628 | | nlmsg = nl_msg_nlmsghdr(reply); |
1629 | | nlmsg->nlmsg_len = reply->size; |
1630 | | |
1631 | | if (!nl_policy_parse(reply, NLMSG_HDRLEN + GENL_HDRLEN, |
1632 | | family_policy, attrs, ARRAY_SIZE(family_policy)) |
1633 | | || nl_attr_get_u16(attrs[CTRL_ATTR_FAMILY_ID]) == 0) { |
1634 | | ofpbuf_delete(reply); |
1635 | | return EPROTO; |
1636 | | } |
1637 | | |
1638 | | *replyp = reply; |
1639 | | return 0; |
1640 | | } |
1641 | | #endif |
1642 | | |
1643 | | /* Finds the multicast group called 'group_name' in genl family 'family_name'. |
1644 | | * When successful, writes its result to 'multicast_group' and returns 0. |
1645 | | * Otherwise, clears 'multicast_group' and returns a positive error code. |
1646 | | */ |
1647 | | int |
1648 | | nl_lookup_genl_mcgroup(const char *family_name, const char *group_name, |
1649 | | unsigned int *multicast_group) |
1650 | 0 | { |
1651 | 0 | struct nlattr *family_attrs[ARRAY_SIZE(family_policy)]; |
1652 | 0 | const struct nlattr *mc; |
1653 | 0 | struct ofpbuf *reply; |
1654 | 0 | unsigned int left; |
1655 | 0 | int error; |
1656 | |
|
1657 | 0 | *multicast_group = 0; |
1658 | 0 | error = do_lookup_genl_family(family_name, family_attrs, &reply); |
1659 | 0 | if (error) { |
1660 | 0 | return error; |
1661 | 0 | } |
1662 | | |
1663 | 0 | if (!family_attrs[CTRL_ATTR_MCAST_GROUPS]) { |
1664 | 0 | error = EPROTO; |
1665 | 0 | goto exit; |
1666 | 0 | } |
1667 | | |
1668 | 0 | NL_NESTED_FOR_EACH (mc, left, family_attrs[CTRL_ATTR_MCAST_GROUPS]) { |
1669 | 0 | static const struct nl_policy mc_policy[] = { |
1670 | 0 | [CTRL_ATTR_MCAST_GRP_ID] = {.type = NL_A_U32}, |
1671 | 0 | [CTRL_ATTR_MCAST_GRP_NAME] = {.type = NL_A_STRING}, |
1672 | 0 | }; |
1673 | |
|
1674 | 0 | struct nlattr *mc_attrs[ARRAY_SIZE(mc_policy)]; |
1675 | 0 | const char *mc_name; |
1676 | |
|
1677 | 0 | if (!nl_parse_nested(mc, mc_policy, mc_attrs, ARRAY_SIZE(mc_policy))) { |
1678 | 0 | error = EPROTO; |
1679 | 0 | goto exit; |
1680 | 0 | } |
1681 | | |
1682 | 0 | mc_name = nl_attr_get_string(mc_attrs[CTRL_ATTR_MCAST_GRP_NAME]); |
1683 | 0 | if (!strcmp(group_name, mc_name)) { |
1684 | 0 | *multicast_group = |
1685 | 0 | nl_attr_get_u32(mc_attrs[CTRL_ATTR_MCAST_GRP_ID]); |
1686 | 0 | error = 0; |
1687 | 0 | goto exit; |
1688 | 0 | } |
1689 | 0 | } |
1690 | 0 | error = EPROTO; |
1691 | |
|
1692 | 0 | exit: |
1693 | 0 | ofpbuf_delete(reply); |
1694 | 0 | return error; |
1695 | 0 | } |
1696 | | |
1697 | | /* If '*number' is 0, translates the given Generic Netlink family 'name' to a |
1698 | | * number and stores it in '*number'. If successful, returns 0 and the caller |
1699 | | * may use '*number' as the family number. On failure, returns a positive |
1700 | | * errno value and '*number' caches the errno value. */ |
1701 | | int |
1702 | | nl_lookup_genl_family(const char *name, int *number) |
1703 | 0 | { |
1704 | 0 | if (*number == 0) { |
1705 | 0 | struct nlattr *attrs[ARRAY_SIZE(family_policy)]; |
1706 | 0 | struct ofpbuf *reply; |
1707 | 0 | int error; |
1708 | |
|
1709 | 0 | error = do_lookup_genl_family(name, attrs, &reply); |
1710 | 0 | if (!error) { |
1711 | 0 | *number = nl_attr_get_u16(attrs[CTRL_ATTR_FAMILY_ID]); |
1712 | 0 | define_genl_family(*number, name); |
1713 | 0 | } else { |
1714 | 0 | *number = -error; |
1715 | 0 | } |
1716 | 0 | ofpbuf_delete(reply); |
1717 | |
|
1718 | 0 | ovs_assert(*number != 0); |
1719 | 0 | } |
1720 | 0 | return *number > 0 ? 0 : -*number; |
1721 | 0 | } |
1722 | | |
1723 | | struct nl_pool { |
1724 | | struct nl_sock *socks[16]; |
1725 | | int n; |
1726 | | }; |
1727 | | |
1728 | | static struct ovs_mutex pool_mutex = OVS_MUTEX_INITIALIZER; |
1729 | | static struct nl_pool pools[MAX_LINKS] OVS_GUARDED_BY(pool_mutex); |
1730 | | |
1731 | | static int |
1732 | | nl_pool_alloc(int protocol, struct nl_sock **sockp) |
1733 | 0 | { |
1734 | 0 | struct nl_sock *sock = NULL; |
1735 | 0 | struct nl_pool *pool; |
1736 | |
|
1737 | 0 | ovs_assert(protocol >= 0 && protocol < ARRAY_SIZE(pools)); |
1738 | |
|
1739 | 0 | ovs_mutex_lock(&pool_mutex); |
1740 | 0 | pool = &pools[protocol]; |
1741 | 0 | if (pool->n > 0) { |
1742 | 0 | sock = pool->socks[--pool->n]; |
1743 | 0 | } |
1744 | 0 | ovs_mutex_unlock(&pool_mutex); |
1745 | |
|
1746 | 0 | if (sock) { |
1747 | 0 | *sockp = sock; |
1748 | 0 | return 0; |
1749 | 0 | } else { |
1750 | 0 | return nl_sock_create(protocol, sockp); |
1751 | 0 | } |
1752 | 0 | } |
1753 | | |
1754 | | static void |
1755 | | nl_pool_release(struct nl_sock *sock) |
1756 | 0 | { |
1757 | 0 | if (sock) { |
1758 | 0 | struct nl_pool *pool = &pools[sock->protocol]; |
1759 | |
|
1760 | 0 | ovs_mutex_lock(&pool_mutex); |
1761 | 0 | if (pool->n < ARRAY_SIZE(pool->socks)) { |
1762 | 0 | pool->socks[pool->n++] = sock; |
1763 | 0 | sock = NULL; |
1764 | 0 | } |
1765 | 0 | ovs_mutex_unlock(&pool_mutex); |
1766 | |
|
1767 | 0 | nl_sock_destroy(sock); |
1768 | 0 | } |
1769 | 0 | } |
1770 | | |
1771 | | /* Sends 'request' to the kernel on a Netlink socket for the given 'protocol' |
1772 | | * (e.g. NETLINK_ROUTE or NETLINK_GENERIC) and waits for a response. If |
1773 | | * successful, returns 0. On failure, returns a positive errno value. |
1774 | | * |
1775 | | * If 'replyp' is nonnull, then on success '*replyp' is set to the kernel's |
1776 | | * reply, which the caller is responsible for freeing with ofpbuf_delete(), and |
1777 | | * on failure '*replyp' is set to NULL. If 'replyp' is null, then the kernel's |
1778 | | * reply, if any, is discarded. |
1779 | | * |
1780 | | * Before the message is sent, nlmsg_len in 'request' will be finalized to |
1781 | | * match msg->size, nlmsg_pid will be set to the pid of the socket used |
1782 | | * for sending the request, and nlmsg_seq will be initialized. |
1783 | | * |
1784 | | * The caller is responsible for destroying 'request'. |
1785 | | * |
1786 | | * Bare Netlink is an unreliable transport protocol. This function layers |
1787 | | * reliable delivery and reply semantics on top of bare Netlink. |
1788 | | * |
1789 | | * In Netlink, sending a request to the kernel is reliable enough, because the |
1790 | | * kernel will tell us if the message cannot be queued (and we will in that |
1791 | | * case put it on the transmit queue and wait until it can be delivered). |
1792 | | * |
1793 | | * Receiving the reply is the real problem: if the socket buffer is full when |
1794 | | * the kernel tries to send the reply, the reply will be dropped. However, the |
1795 | | * kernel sets a flag that a reply has been dropped. The next call to recv |
1796 | | * then returns ENOBUFS. We can then re-send the request. |
1797 | | * |
1798 | | * Caveats: |
1799 | | * |
1800 | | * 1. Netlink depends on sequence numbers to match up requests and |
1801 | | * replies. The sender of a request supplies a sequence number, and |
1802 | | * the reply echos back that sequence number. |
1803 | | * |
1804 | | * This is fine, but (1) some kernel netlink implementations are |
1805 | | * broken, in that they fail to echo sequence numbers and (2) this |
1806 | | * function will drop packets with non-matching sequence numbers, so |
1807 | | * that only a single request can be usefully transacted at a time. |
1808 | | * |
1809 | | * 2. Resending the request causes it to be re-executed, so the request |
1810 | | * needs to be idempotent. |
1811 | | */ |
1812 | | int |
1813 | | nl_transact(int protocol, const struct ofpbuf *request, |
1814 | | struct ofpbuf **replyp) |
1815 | 0 | { |
1816 | 0 | struct nl_sock *sock; |
1817 | 0 | int error; |
1818 | |
|
1819 | 0 | error = nl_pool_alloc(protocol, &sock); |
1820 | 0 | if (error) { |
1821 | 0 | if (replyp) { |
1822 | 0 | *replyp = NULL; |
1823 | 0 | } |
1824 | 0 | return error; |
1825 | 0 | } |
1826 | | |
1827 | 0 | error = nl_sock_transact(sock, request, replyp); |
1828 | |
|
1829 | 0 | nl_pool_release(sock); |
1830 | 0 | return error; |
1831 | 0 | } |
1832 | | |
1833 | | /* Sends the 'request' member of the 'n' transactions in 'transactions' on a |
1834 | | * Netlink socket for the given 'protocol' (e.g. NETLINK_ROUTE or |
1835 | | * NETLINK_GENERIC), in order, and receives responses to all of them. Fills in |
1836 | | * the 'error' member of each transaction with 0 if it was successful, |
1837 | | * otherwise with a positive errno value. If 'reply' is nonnull, then it will |
1838 | | * be filled with the reply if the message receives a detailed reply. In other |
1839 | | * cases, i.e. where the request failed or had no reply beyond an indication of |
1840 | | * success, 'reply' will be cleared if it is nonnull. |
1841 | | * |
1842 | | * The caller is responsible for destroying each request and reply, and the |
1843 | | * transactions array itself. |
1844 | | * |
1845 | | * Before sending each message, this function will finalize nlmsg_len in each |
1846 | | * 'request' to match the ofpbuf's size, set nlmsg_pid to the pid of the socket |
1847 | | * used for the transaction, and initialize nlmsg_seq. |
1848 | | * |
1849 | | * Bare Netlink is an unreliable transport protocol. This function layers |
1850 | | * reliable delivery and reply semantics on top of bare Netlink. See |
1851 | | * nl_transact() for some caveats. |
1852 | | */ |
1853 | | void |
1854 | | nl_transact_multiple(int protocol, |
1855 | | struct nl_transaction **transactions, size_t n) |
1856 | 0 | { |
1857 | 0 | struct nl_sock *sock; |
1858 | 0 | int error; |
1859 | |
|
1860 | 0 | error = nl_pool_alloc(protocol, &sock); |
1861 | 0 | if (!error) { |
1862 | 0 | nl_sock_transact_multiple(sock, transactions, n); |
1863 | 0 | nl_pool_release(sock); |
1864 | 0 | } else { |
1865 | 0 | nl_sock_record_errors__(transactions, n, error); |
1866 | 0 | } |
1867 | 0 | } |
1868 | | |
1869 | | |
1870 | | static uint32_t |
1871 | | nl_sock_allocate_seq(struct nl_sock *sock, unsigned int n) |
1872 | 0 | { |
1873 | 0 | uint32_t seq = sock->next_seq; |
1874 | |
|
1875 | 0 | sock->next_seq += n; |
1876 | | |
1877 | | /* Make it impossible for the next request for sequence numbers to wrap |
1878 | | * around to 0. Start over with 1 to avoid ever using a sequence number of |
1879 | | * 0, because the kernel uses sequence number 0 for notifications. */ |
1880 | 0 | if (sock->next_seq >= UINT32_MAX / 2) { |
1881 | 0 | sock->next_seq = 1; |
1882 | 0 | } |
1883 | |
|
1884 | 0 | return seq; |
1885 | 0 | } |
1886 | | |
1887 | | static void |
1888 | | nlmsghdr_to_string(const struct nlmsghdr *h, int protocol, struct ds *ds) |
1889 | 0 | { |
1890 | 0 | struct nlmsg_flag { |
1891 | 0 | unsigned int bits; |
1892 | 0 | const char *name; |
1893 | 0 | }; |
1894 | 0 | static const struct nlmsg_flag flags[] = { |
1895 | 0 | { NLM_F_REQUEST, "REQUEST" }, |
1896 | 0 | { NLM_F_MULTI, "MULTI" }, |
1897 | 0 | { NLM_F_ACK, "ACK" }, |
1898 | 0 | { NLM_F_ECHO, "ECHO" }, |
1899 | 0 | { NLM_F_DUMP, "DUMP" }, |
1900 | 0 | { NLM_F_ROOT, "ROOT" }, |
1901 | 0 | { NLM_F_MATCH, "MATCH" }, |
1902 | 0 | { NLM_F_ATOMIC, "ATOMIC" }, |
1903 | 0 | }; |
1904 | 0 | const struct nlmsg_flag *flag; |
1905 | 0 | uint16_t flags_left; |
1906 | |
|
1907 | 0 | ds_put_format(ds, "nl(len:%"PRIu32", type=%"PRIu16, |
1908 | 0 | h->nlmsg_len, h->nlmsg_type); |
1909 | 0 | if (h->nlmsg_type == NLMSG_NOOP) { |
1910 | 0 | ds_put_cstr(ds, "(no-op)"); |
1911 | 0 | } else if (h->nlmsg_type == NLMSG_ERROR) { |
1912 | 0 | ds_put_cstr(ds, "(error)"); |
1913 | 0 | } else if (h->nlmsg_type == NLMSG_DONE) { |
1914 | 0 | ds_put_cstr(ds, "(done)"); |
1915 | 0 | } else if (h->nlmsg_type == NLMSG_OVERRUN) { |
1916 | 0 | ds_put_cstr(ds, "(overrun)"); |
1917 | 0 | } else if (h->nlmsg_type < NLMSG_MIN_TYPE) { |
1918 | 0 | ds_put_cstr(ds, "(reserved)"); |
1919 | 0 | } else if (protocol == NETLINK_GENERIC) { |
1920 | 0 | ds_put_format(ds, "(%s)", genl_family_to_name(h->nlmsg_type)); |
1921 | 0 | } else { |
1922 | 0 | ds_put_cstr(ds, "(family-defined)"); |
1923 | 0 | } |
1924 | 0 | ds_put_format(ds, ", flags=%"PRIx16, h->nlmsg_flags); |
1925 | 0 | flags_left = h->nlmsg_flags; |
1926 | 0 | for (flag = flags; flag < &flags[ARRAY_SIZE(flags)]; flag++) { |
1927 | 0 | if ((flags_left & flag->bits) == flag->bits) { |
1928 | 0 | ds_put_format(ds, "[%s]", flag->name); |
1929 | 0 | flags_left &= ~flag->bits; |
1930 | 0 | } |
1931 | 0 | } |
1932 | 0 | if (flags_left) { |
1933 | 0 | ds_put_format(ds, "[OTHER:%"PRIx16"]", flags_left); |
1934 | 0 | } |
1935 | 0 | ds_put_format(ds, ", seq=%"PRIx32", pid=%"PRIu32, |
1936 | 0 | h->nlmsg_seq, h->nlmsg_pid); |
1937 | 0 | } |
1938 | | |
1939 | | static char * |
1940 | | nlmsg_to_string(const struct ofpbuf *buffer, int protocol) |
1941 | 0 | { |
1942 | 0 | struct ds ds = DS_EMPTY_INITIALIZER; |
1943 | 0 | const struct nlmsghdr *h = ofpbuf_at(buffer, 0, NLMSG_HDRLEN); |
1944 | 0 | if (h) { |
1945 | 0 | nlmsghdr_to_string(h, protocol, &ds); |
1946 | 0 | if (h->nlmsg_type == NLMSG_ERROR) { |
1947 | 0 | const struct nlmsgerr *e; |
1948 | 0 | e = ofpbuf_at(buffer, NLMSG_HDRLEN, |
1949 | 0 | NLMSG_ALIGN(sizeof(struct nlmsgerr))); |
1950 | 0 | if (e) { |
1951 | 0 | ds_put_format(&ds, " error(%d", e->error); |
1952 | 0 | if (e->error < 0) { |
1953 | 0 | ds_put_format(&ds, "(%s)", ovs_strerror(-e->error)); |
1954 | 0 | } |
1955 | 0 | ds_put_cstr(&ds, ", in-reply-to("); |
1956 | 0 | nlmsghdr_to_string(&e->msg, protocol, &ds); |
1957 | 0 | ds_put_cstr(&ds, "))"); |
1958 | 0 | } else { |
1959 | 0 | ds_put_cstr(&ds, " error(truncated)"); |
1960 | 0 | } |
1961 | 0 | } else if (h->nlmsg_type == NLMSG_DONE) { |
1962 | 0 | int *error = ofpbuf_at(buffer, NLMSG_HDRLEN, sizeof *error); |
1963 | 0 | if (error) { |
1964 | 0 | ds_put_format(&ds, " done(%d", *error); |
1965 | 0 | if (*error < 0) { |
1966 | 0 | ds_put_format(&ds, "(%s)", ovs_strerror(-*error)); |
1967 | 0 | } |
1968 | 0 | ds_put_cstr(&ds, ")"); |
1969 | 0 | } else { |
1970 | 0 | ds_put_cstr(&ds, " done(truncated)"); |
1971 | 0 | } |
1972 | 0 | } else if (protocol == NETLINK_GENERIC) { |
1973 | 0 | struct genlmsghdr *genl = nl_msg_genlmsghdr(buffer); |
1974 | 0 | if (genl) { |
1975 | 0 | ds_put_format(&ds, ",genl(cmd=%"PRIu8",version=%"PRIu8")", |
1976 | 0 | genl->cmd, genl->version); |
1977 | 0 | } |
1978 | 0 | } |
1979 | 0 | } else { |
1980 | 0 | ds_put_cstr(&ds, "nl(truncated)"); |
1981 | 0 | } |
1982 | 0 | return ds.string; |
1983 | 0 | } |
1984 | | |
1985 | | static void |
1986 | | log_nlmsg(const char *function, int error, |
1987 | | const void *message, size_t size, int protocol) |
1988 | 0 | { |
1989 | 0 | if (!VLOG_IS_DBG_ENABLED()) { |
1990 | 0 | return; |
1991 | 0 | } |
1992 | | |
1993 | 0 | struct ofpbuf buffer = ofpbuf_const_initializer(message, size); |
1994 | 0 | char *nlmsg = nlmsg_to_string(&buffer, protocol); |
1995 | 0 | VLOG_DBG_RL(&rl, "%s (%s): %s", function, ovs_strerror(error), nlmsg); |
1996 | 0 | free(nlmsg); |
1997 | 0 | } |