The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
control.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: bfff00040856d6db11cbd363c142bed189dd0340 $
19 *
20 * @brief Control-plane signaling
21 * @file io/control.c
22 *
23 * @copyright 2016 Alan DeKok (aland@freeradius.org)
24 */
25RCSID("$Id: bfff00040856d6db11cbd363c142bed189dd0340 $")
26
27#include <freeradius-devel/io/atomic_queue.h>
28#include <freeradius-devel/io/control.h>
29#include <freeradius-devel/util/debug.h>
30#include <freeradius-devel/util/strerror.h>
31#include <freeradius-devel/util/syserror.h>
32#include <freeradius-devel/util/misc.h>
33#include <freeradius-devel/util/rand.h>
34
35#ifdef HAVE_STDATOMIC_H
36# include <stdatomic.h>
37#else
38# include <freeradius-devel/util/stdatomic.h>
39#endif
40
41#include <fcntl.h>
42#include <pthread.h>
43#include <stddef.h>
44#include <sys/event.h>
45#include <sys/socket.h>
46#include <poll.h>
47
48/*
49 * A message buffer large enough for any element the queue accepts.
50 */
51#define CACHE_LINE_BYTES (128)
52
53/**
54 * The header of every message
55 *
56 * A message is this header followed by data_size bytes, copied by
57 * value into the receiver's queue. The queue places elements 8 byte
58 * aligned, and the header is 8 bytes, so callbacks can read their
59 * structs straight out of the data.
60 */
61typedef struct {
62 fr_control_eventset_t es; //!< event set of this message
63 uint16_t event; //!< event this message signals, within its event set
64 uint32_t data_size; //!< size of the data we're sending
66
67static_assert(sizeof(fr_control_header_t) == 8, "control message data must stay 8 byte aligned");
68
69/**
70 * Ancillary data for the one socket a datagram may carry
71 *
72 * Used on both sides. Aligned as the CMSG macros require, without
73 * embedding a cmsghdr, as on Linux that ends in a flexible array and
74 * cannot then sit in an array of these.
75 */
76typedef struct {
77 _Alignas(struct cmsghdr) uint8_t buf[CMSG_SPACE(sizeof(int))]; //!< one cmsghdr and one int.
79
80/*
81 * Datagrams one recvmmsg() takes off the wakeup socket. Most are
82 * wakeups. The default buffer holds about 32 on macOS and about
83 * 280 on Linux before senders see it as full, so one batch usually
84 * empties it on macOS, and takes a few calls on Linux.
85 */
86#define CONTROL_SOCKET_MSGS_PER_READ (64)
87
88/*
89 * Datagrams carrying a socket the wakeup socket should hold. Linux
90 * doubles a buffer request and clamps it at twice net.core.wmem_max
91 * and rmem_max, so with their default of 212992 this is about the
92 * most that fits there.
93 */
94#define CONTROL_SOCKET_DATAGRAMS (512)
95
96/*
97 * What one datagram carrying a socket takes up in a socket buffer,
98 * which is the kernel's own bookkeeping and not the bytes sent.
99 * Measured once, the first time a control is opened. The initial
100 * value is what Linux was measured at, and is used if the
101 * measurement fails.
102 */
104static pthread_once_t control_socket_dgram_size_once = PTHREAD_ONCE_INIT;
105
106/** Measure what one datagram carrying a socket takes up in a socket buffer
107 *
108 */
110{
111 int sv[2];
112 int bufsize = 65536;
113 int sndbuf, rcvbuf;
114 socklen_t len;
115 fr_control_header_t hdr = {};
117 struct iovec iov;
118 struct msghdr mh;
119 struct cmsghdr *ch;
120 unsigned int num = 0;
121
122 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) return;
123
124 (void) setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
125 (void) setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
126 (void) fr_nonblock(sv[0]);
127 (void) fr_nonblock(sv[1]);
128
129 iov.iov_base = &hdr;
130 iov.iov_len = sizeof(hdr);
131
132 memset(&cmsg, 0, sizeof(cmsg));
133 memset(&mh, 0, sizeof(mh));
134 mh.msg_iov = &iov;
135 mh.msg_iovlen = 1;
136 mh.msg_control = &cmsg;
137 mh.msg_controllen = sizeof(cmsg);
138
139 ch = CMSG_FIRSTHDR(&mh);
140 ch->cmsg_level = SOL_SOCKET;
141 ch->cmsg_type = SCM_RIGHTS;
142 ch->cmsg_len = CMSG_LEN(sizeof(int));
143 memcpy(CMSG_DATA(ch), &sv[1], sizeof(int));
144
145 while (sendmsg(sv[1], &mh, 0) == sizeof(hdr)) num++;
146
147 /*
148 * Whichever side the kernel counts against, both were asked
149 * for the same size, so the smaller of what it granted is the
150 * bound.
151 */
152 len = sizeof(sndbuf);
153 if (getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, &len) < 0) sndbuf = bufsize;
154 len = sizeof(rcvbuf);
155 if (getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len) < 0) rcvbuf = bufsize;
156 if (num > 0) control_socket_dgram_size_actual = ((sndbuf < rcvbuf) ? sndbuf : rcvbuf) / num;
157
158 while (num > 0) {
159 int sock = -1;
160
161 mh.msg_controllen = sizeof(cmsg);
162 if (recvmsg(sv[0], &mh, 0) < 0) break;
163 ch = CMSG_FIRSTHDR(&mh);
164 if (ch && (ch->cmsg_level == SOL_SOCKET) && (ch->cmsg_type == SCM_RIGHTS)) {
165 memcpy(&sock, CMSG_DATA(ch), sizeof(sock));
166 close(sock);
167 }
168 num--;
169 }
170
171 close(sv[0]);
172 close(sv[1]);
173}
174
175/*
176 * Received sockets must be close-on-exec. Linux can set that as
177 * they are received, elsewhere it is set just after.
178 */
179#ifdef MSG_CMSG_CLOEXEC
180# define CONTROL_RECV_FLAGS MSG_CMSG_CLOEXEC
181#else
182# define CONTROL_RECV_FLAGS 0
183#endif
184
185typedef struct {
186 fr_control_callback_t callback; //!< the function to call
187 void *uctx; //!< context for the callback
189
190typedef struct {
191 fr_control_socket_callback_t callback; //!< the function to call
192 void *uctx; //!< context for the callback
194
195/**
196 * The dispatch table for one event set
197 */
198typedef struct {
199 uint16_t events_num; //!< the size of the callback array
200 fr_control_ctx_t *events; //!< callbacks, indexed by event
201
202 uint16_t socket_events_num; //!< the size of the socket callback array
203 fr_control_socket_ctx_t *socket_events; //!< callbacks for messages carrying a socket,
204 ///< indexed by event
206
207
208/**
209 * The control structure.
210 */
212 fr_event_list_t *el; //!< our event list
213
214 uint16_t slots; //!< messages the queue holds unread.
215 uint16_t max_size; //!< the largest payload a message may carry.
216
217 fr_atomic_queue_t *aq; //!< the messages, header and data by value.
218
219 struct {
220 struct mmsghdr msgs[CONTROL_SOCKET_MSGS_PER_READ]; //!< one per datagram, for recvmmsg().
221 struct iovec iov[CONTROL_SOCKET_MSGS_PER_READ]; //!< one per datagram.
222 fr_control_header_t hdr[CONTROL_SOCKET_MSGS_PER_READ]; //!< where the datagrams land.
223 control_socket_cmsg_t cmsg[CONTROL_SOCKET_MSGS_PER_READ]; //!< where their sockets land.
225
226 int fd[2]; //!< wakeup socketpair. [0] is read by the event loop,
227 ///< [1] is written by the senders.
228
229 bool same_thread; //!< are the two ends in the same thread
230
231 bool opened; //!< has the control path been opened.
232
233 atomic_bool sleeping; //!< the reader is blocked waiting for a signal.
234
236};
237
238/** Find the callback registered for a message
239 *
240 * @param[in] c the control structure
241 * @param[in] es the event set of the message
242 * @param[in] ev the event, within its event set
243 * @return
244 * - NULL if nothing is registered for this event set and event.
245 * - the callback entry otherwise.
246 */
248{
249 fr_control_eventset_table_t const *eventset;
250
251 if (es >= FR_CONTROL_EVENTSET_MAX) return NULL;
252
253 eventset = &c->eventsets[es];
254 if (ev >= eventset->events_num) return NULL;
255 if (!eventset->events[ev].callback) return NULL;
256
257 return &eventset->events[ev];
258}
259
260/** The size of one queued message: header and the largest payload
261 */
262static inline size_t control_message_size(fr_control_t const *c)
263{
264 return sizeof(fr_control_header_t) + c->max_size;
265}
266
267/** Dispatch every queued message
268 *
269 * Called from the reading thread only.
270 *
271 * @param[in] c the control structure.
272 * @return how many messages were dispatched.
273 */
274static inline unsigned int control_service(fr_control_t *c)
275{
276 fr_time_t now = fr_time();
278 unsigned int num = 0;
279
280 while (fr_atomic_queue_spsc_pop(c->aq, rec)) {
281 fr_control_header_t const *hdr = (fr_control_header_t const *) rec;
282 fr_control_ctx_t const *cctx = control_ctx_find(c, hdr->es, hdr->event);
283
284 num++;
285 if (!cctx) continue;
286
287 cctx->callback(rec + sizeof(*hdr), hdr->data_size, now, cctx->uctx);
288 }
289
290 return num;
291}
292
293/** Dispatch one datagram taken off the wakeup socket
294 *
295 * @param[in] c the control structure.
296 * @param[in] mmh the recvmmsg() slot the datagram landed in.
297 * @param[in] hdr the datagram, which should be a bare message header.
298 * @param[in] now when the batch was read.
299 */
300static void control_socket_dispatch(fr_control_t *c, struct mmsghdr *mmh, fr_control_header_t const *hdr,
301 fr_time_t now)
302{
303 struct msghdr *mh = &mmh->msg_hdr;
304 struct cmsghdr *ch = CMSG_FIRSTHDR(mh);
305 fr_control_socket_ctx_t const *cctx = NULL;
306 int sock;
307
308 if (!ch || (ch->cmsg_level != SOL_SOCKET) || (ch->cmsg_type != SCM_RIGHTS) ||
309 (ch->cmsg_len != CMSG_LEN(sizeof(int)))) {
310 fr_cond_assert_msg(!(mh->msg_flags & MSG_CTRUNC), "Control socket message truncated");
311 return;
312 }
313 memcpy(&sock, CMSG_DATA(ch), sizeof(sock));
314#ifndef MSG_CMSG_CLOEXEC
315 (void) fr_cloexec(sock);
316#endif
317
318 if (!fr_cond_assert_msg(!(mh->msg_flags & (MSG_TRUNC | MSG_CTRUNC)), "Control socket message truncated") ||
319 !fr_cond_assert_msg(mmh->msg_len == sizeof(*hdr), "Malformed control message with socket")) {
320 close(sock);
321 return;
322 }
323
324 if ((hdr->es < FR_CONTROL_EVENTSET_MAX) && (hdr->event < c->eventsets[hdr->es].socket_events_num)) {
325 cctx = &c->eventsets[hdr->es].socket_events[hdr->event];
326 }
327 if (!fr_cond_assert_msg(cctx && cctx->callback, "No callback for socket event %u in event set %u",
328 hdr->event, hdr->es)) {
329 close(sock);
330 return;
331 }
332
333 cctx->callback(sock, now, cctx->uctx);
334}
335
336/** Take a batch of datagrams off the wakeup socket, then dispatch every queued message
337 *
338 * Each datagram is a wakeup, announcing that a message was queued while
339 * we were asleep, or a message carying file descriptors in its metdata.
340 */
341static void control_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
342{
343 fr_control_t *c = talloc_get_type_abort(uctx, fr_control_t);
344 int num, i;
345
346 for (i = 0; i < CONTROL_SOCKET_MSGS_PER_READ; i++) {
347 c->socket.msgs[i].msg_hdr.msg_controllen = sizeof(c->socket.cmsg[i]);
348 c->socket.msgs[i].msg_hdr.msg_flags = 0;
349 }
350
351 do {
353 } while ((num < 0) && (errno == EINTR));
354
355 if (num > 0) {
356 fr_time_t now = fr_time();
357
358 for (i = 0; i < num; i++) control_socket_dispatch(c, &c->socket.msgs[i], &c->socket.hdr[i], now);
359 }
360
361 (void) control_service(c);
362}
363
364/** Announce that the reader is about to block, and drain the queue one last time
365 *
366 * The event list runs this when the loop reading this control is about
367 * to idle, so every control read by a loop announces itself, whether or
368 * not the loop knows about it.
369 *
370 * @param[in] uctx the control structure.
371 * @return
372 * - 1 if messages were found, so the loop must not block.
373 * - 0 if the queue was empty.
374 */
375static int control_pre_event(UNUSED fr_time_t now, UNUSED fr_time_delta_t wake, void *uctx)
376{
377 fr_control_t *c = talloc_get_type_abort(uctx, fr_control_t);
378
379 return fr_control_sleeping(c) ? 1 : 0;
380}
381
382/** The reader is running again
383 *
384 * @param[in] uctx the control structure.
385 */
387{
388 fr_control_t *c = talloc_get_type_abort(uctx, fr_control_t);
389
391}
392
393/** Free a control structure
394 *
395 * Removes the socket and the idle callbacks from the event loop, and
396 * closes both ends.
397 *
398 * @param[in] c the control structure
399 */
401{
402 (void) talloc_get_type_abort(c, fr_control_t);
403
404#ifndef NDEBUG
405 (void) fr_event_fd_unarmour(c->el, c->fd[0], FR_EVENT_FILTER_IO, (uintptr_t)c);
406#endif
407 (void) fr_event_fd_delete(c->el, c->fd[0], FR_EVENT_FILTER_IO);
410
411 close(c->fd[0]);
412 close(c->fd[1]);
413
414 return 0;
415}
416
417/** Create a control-plane signaling path.
418 *
419 * @param[in] ctx the talloc context
420 * @param[in] el the event list for the control socket
421 * @param[in] slots how many messages the socket holds unread.
422 * @param[in] max_size the largest payload a message may carry.
423 * @return
424 * - NULL on error
425 * - fr_control_t on success
426 */
428{
429 fr_control_t *c;
430
431 MEM(c = talloc_zero(ctx, fr_control_t));
432 c->el = el;
433 c->slots = slots;
434 c->max_size = max_size;
435
436 return c;
437}
438
439/** Open the control-plane signalling path
440 *
441 * @param[in] c the control-plane to open
442 * @return
443 * - 0 on success
444 * - -1 on failure
445 */
447{
448 int i;
449 int bufsize;
450
452
453 /*
454 * A datagram socketpair for the wakeups. Once it is full the
455 * reader has wakeups it has not consumed, and further writes
456 * fail cheaply instead of queueing. A socket can also carry
457 * descriptors as ancillary data, and the two ends can live in
458 * different processes.
459 */
460 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, c->fd) < 0) {
461 fr_strerror_printf("Failed opening socketpair for control socket: %s", fr_syserror(errno));
462 return -1;
463 }
464 talloc_set_destructor(c, _control_free);
465
466 /*
467 * The default buffer holds a few dozen datagrams. Wakeups only
468 * go to a sleeping reader, so they never need more, but a
469 * datagram carrying a socket is refused when the buffer is
470 * full, so make room for a reasonable number of those.
471 */
473 (void) setsockopt(c->fd[0], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
474 (void) setsockopt(c->fd[1], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
475
476 /*
477 * We don't want reads from the socket to be blocking.
478 */
479 (void) fr_nonblock(c->fd[0]);
480 (void) fr_nonblock(c->fd[1]);
481 (void) fr_cloexec(c->fd[0]);
482 (void) fr_cloexec(c->fd[1]);
483
484 /*
485 * Room for "slots" unread messages.
486 */
488 if (!c->aq) {
489 fr_strerror_const("Failed creating control message queue");
490 return -1;
491 }
492
493 /*
494 * Point each recvmmsg() slot at its own vector, datagram
495 * buffer, and ancillary buffer. Everything else in a slot
496 * stays zero from talloc_zero().
497 */
498 for (i = 0; i < CONTROL_SOCKET_MSGS_PER_READ; i++) {
499 c->socket.iov[i].iov_base = &c->socket.hdr[i];
500 c->socket.iov[i].iov_len = sizeof(c->socket.hdr[i]);
501 c->socket.msgs[i].msg_hdr.msg_iov = &c->socket.iov[i];
502 c->socket.msgs[i].msg_hdr.msg_iovlen = 1;
503 c->socket.msgs[i].msg_hdr.msg_control = &c->socket.cmsg[i];
504 }
505
506 if (fr_event_fd_insert(c, NULL, c->el, c->fd[0], control_read, NULL, NULL, c) < 0) {
507 fr_strerror_const_push("Failed adding FD to event list control socket");
508 return -1;
509 }
510
511#ifndef NDEBUG
512 (void) fr_event_fd_armour(c->el, c->fd[0], FR_EVENT_FILTER_IO, (uintptr_t)c);
513#endif
514
515 /*
516 * Senders only wake a reader which has announced it is
517 * blocking. The event list tells us when that is about
518 * to happen, and when it is over.
519 */
520 if ((fr_event_pre_insert(c->el, control_pre_event, c) < 0) ||
522 fr_strerror_const_push("Failed adding idle callbacks for control socket");
523 return -1;
524 }
525 c->opened = true;
526
527 return 0;
528}
529
530/** Send a control-plane message
531 *
532 * Called from the originating threads. The message is copied into
533 * the receiver's queue, then a byte is written to the wakeup socket.
534 *
535 * @param[in] c the control structure
536 * @param[in] es the event set of this message.
537 * @param[in] ev the event this message signals, within its event set.
538 * @param[in] data the data to write to the control plane
539 * @param[in] data_size the size of the data to write to the control plane.
540 * @return
541 * - <0 on error, including the queue being full.
542 * - 0 on success
543 */
545 void const *data, size_t data_size)
546{
549 ssize_t slen;
550
551 (void) talloc_get_type_abort(c, fr_control_t);
552
553 if (c->same_thread) {
554 fr_control_ctx_t const *cctx = control_ctx_find(c, es, ev);
555
556 if (!cctx) return -1;
557
558 cctx->callback(data, data_size, fr_time(), cctx->uctx);
559 return 0;
560 }
561
562 if (!fr_cond_assert_msg(data_size <= c->max_size, "Control message of %zu bytes exceeds max_size %u",
563 data_size, c->max_size)) return -1;
564
565 hdr->es = es;
566 hdr->event = ev;
567 hdr->data_size = data_size;
568 memcpy(rec + sizeof(*hdr), data, data_size);
569
570 if (!fr_atomic_queue_mpmc_push(c->aq, rec)) {
571 fr_strerror_const("Control message queue full");
572 return -1;
573 }
574
575 if (!fr_control_is_sleeping(c)) return 0;
576
577 /*
578 * Wake the reader. A full socket means it has wakeups it
579 * has not consumed, so this one is not needed. Linux reports
580 * a full datagram socket as EAGAIN, macOS as ENOBUFS.
581 */
582 do {
583 slen = write(c->fd[1], ".", 1);
584 } while ((slen < 0) && (errno == EINTR));
585
586 if ((slen < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != ENOBUFS)) {
587 fr_strerror_printf("Failed waking control reader: %s", fr_syserror(errno));
588 return -1;
589 }
590
591 return 0;
592}
593
594/** Send a control-plane message carrying a socket
595 *
596 * @param[in] c the control structure
597 * @param[in] es the event set of this message.
598 * @param[in] ev the event this message signals, within its event set.
599 * @param[in] sock the socket to send.
600 * @return
601 * - <0 on error, including the wakeup socket being full.
602 * - 0 on success
603 */
605{
606 fr_control_header_t hdr = {
607 .es = es,
608 .event = ev
609 };
611 struct cmsghdr *ch;
612 struct iovec iov;
613 struct msghdr mh;
614 ssize_t slen;
615
616 (void) talloc_get_type_abort(c, fr_control_t);
617
618 if (!fr_cond_assert_msg(!c->same_thread, "Control messages with sockets need a socket")) return -1;
619
620 iov.iov_base = &hdr;
621 iov.iov_len = sizeof(hdr);
622
623 memset(&cmsg, 0, sizeof(cmsg));
624 memset(&mh, 0, sizeof(mh));
625 mh.msg_iov = &iov;
626 mh.msg_iovlen = 1;
627 mh.msg_control = &cmsg;
628 mh.msg_controllen = sizeof(cmsg);
629
630 ch = CMSG_FIRSTHDR(&mh);
631 ch->cmsg_level = SOL_SOCKET;
632 ch->cmsg_type = SCM_RIGHTS;
633 ch->cmsg_len = CMSG_LEN(sizeof(sock));
634 memcpy(CMSG_DATA(ch), &sock, sizeof(sock));
635
636 do {
637 slen = sendmsg(c->fd[1], &mh, 0);
638 } while ((slen < 0) && (errno == EINTR));
639
640 if (slen < 0) {
641 fr_strerror_printf("Failed sending control message with socket: %s", fr_syserror(errno));
642 return -1;
643 }
644
645 return 0;
646}
647
648/** Register a callback for a message
649 *
650 * @param[in] c the control structure
651 * @param[in] es the event set of the message.
652 * @param[in] ev the event, within its event set.
653 * @param[in] callback the callback function
654 * @param[in] uctx the context passed to the callback
655 * @return
656 * - <0 on error
657 * - 0 on success
658 */
660 fr_control_callback_t callback, void *uctx)
661{
663
664 (void) talloc_get_type_abort(c, fr_control_t);
665
666 if (c->opened) {
667 fr_strerror_printf("Cannot add callbacks after the control is opened");
668 return -1;
669 }
670
671 if (es >= FR_CONTROL_EVENTSET_MAX) {
672 fr_strerror_printf("Unknown control event set %" PRIu16, es);
673 return -1;
674 }
675 eventset = &c->eventsets[es];
676
677 /*
678 * If there is not enough space in the array of callbacks
679 * re-allocate it with a larger one. The array is a child
680 * of the control, so the control itself never moves.
681 */
682 if (ev >= eventset->events_num) {
683 MEM(eventset->events = talloc_realloc(c, eventset->events, fr_control_ctx_t, ev + 1));
684
685 /*
686 * Zero the additional callback entries.
687 */
688 memset(eventset->events + eventset->events_num, 0,
689 (ev + 1 - eventset->events_num) * sizeof(*eventset->events));
690 eventset->events_num = ev + 1;
691 }
692
693 /*
694 * Re-registering the same thing is OK.
695 */
696 if ((eventset->events[ev].uctx == uctx) &&
697 (eventset->events[ev].callback == callback)) {
698 return 0;
699 }
700
701 if (eventset->events[ev].callback != NULL) {
702 fr_strerror_const("Callback is already set");
703 return -1;
704 }
705
706 eventset->events[ev].uctx = uctx;
707 eventset->events[ev].callback = callback;
708
709 return 0;
710}
711
712/** Register a callback for a message which carries a socket
713 *
714 * Socket events are numbered separately from message events within an
715 * event set, so the same number may be registered with both this and
716 * fr_control_callback_add(). They are sent with fr_control_socket_send().
717 *
718 * @param[in] c the control structure
719 * @param[in] es the event set of the message.
720 * @param[in] ev the event, within its event set.
721 * @param[in] callback the callback function
722 * @param[in] uctx the context passed to the callback
723 * @return
724 * - <0 on error
725 * - 0 on success
726 */
728 fr_control_socket_callback_t callback, void *uctx)
729{
731
732 (void) talloc_get_type_abort(c, fr_control_t);
733
734 if (c->opened) {
735 fr_strerror_printf("Cannot add callbacks after the control is opened");
736 return -1;
737 }
738
739 if (es >= FR_CONTROL_EVENTSET_MAX) {
740 fr_strerror_printf("Unknown control event set %" PRIu16, es);
741 return -1;
742 }
743 eventset = &c->eventsets[es];
744
745 /*
746 * If there is not enough space in the array of callbacks
747 * re-allocate it with a larger one. The array is a child
748 * of the control, so the control itself never moves.
749 */
750 if (ev >= eventset->socket_events_num) {
751 MEM(eventset->socket_events = talloc_realloc(c, eventset->socket_events,
752 fr_control_socket_ctx_t, ev + 1));
753 memset(eventset->socket_events + eventset->socket_events_num, 0,
754 (ev + 1 - eventset->socket_events_num) * sizeof(*eventset->socket_events));
755 eventset->socket_events_num = ev + 1;
756 }
757
758 /*
759 * Re-registering the same thing is OK.
760 */
761 if ((eventset->socket_events[ev].uctx == uctx) &&
762 (eventset->socket_events[ev].callback == callback)) {
763 return 0;
764 }
765
766 if (eventset->socket_events[ev].callback != NULL) {
767 fr_strerror_const("Callback is already set");
768 return -1;
769 }
770
771 eventset->socket_events[ev].uctx = uctx;
772 eventset->socket_events[ev].callback = callback;
773
774 return 0;
775}
776
777/** Delete a callback for a message
778 *
779 * @param[in] c the control structure
780 * @param[in] es the event set of the message.
781 * @param[in] ev the event, within its event set.
782 * @return
783 * - <0 on error
784 * - 0 on success
785 */
787{
789
790 (void) talloc_get_type_abort(c, fr_control_t);
791
792 if ((es >= FR_CONTROL_EVENTSET_MAX) || (ev >= c->eventsets[es].events_num)) {
793 fr_strerror_printf("Failed deleting unknown event %" PRIu16 " in event set %" PRIu16, ev, es);
794 return -1;
795 }
796 eventset = &c->eventsets[es];
797
798 eventset->events[ev].uctx = NULL;
799 eventset->events[ev].callback = NULL;
800
801 return 0;
802}
803
804/** Delete a callback for a message which carries a socket
805 *
806 * @param[in] c the control structure
807 * @param[in] es the event set of the message.
808 * @param[in] ev the event, within its event set.
809 * @return
810 * - <0 on error
811 * - 0 on success
812 */
814{
816
817 (void) talloc_get_type_abort(c, fr_control_t);
818
819 if ((es >= FR_CONTROL_EVENTSET_MAX) || (ev >= c->eventsets[es].socket_events_num)) {
820 fr_strerror_printf("Failed deleting unknown socket event %" PRIu16 " in event set %" PRIu16, ev, es);
821 return -1;
822 }
823 eventset = &c->eventsets[es];
824
825 eventset->socket_events[ev].uctx = NULL;
826 eventset->socket_events[ev].callback = NULL;
827
828 return 0;
829}
830
831/** Record that the reader of this control plane is about to block
832 *
833 * Call this before blocking, then check any other work queues one last
834 * time. A sender pushes work, then checks this flag. The seq_cst
835 * fences stop either side reordering its store after its load, so one
836 * of them always sees the other.
837 *
838 * @param[in] c the control structure.
839 * @return
840 * - true if messages were serviced, so the caller must not block.
841 * - false if the queue was empty.
842 */
844{
847
848 if (control_service(c) == 0) return false;
849
851 return true;
852}
853
854/** Record that the reader of this control plane is running again
855 *
856 * Call this as soon as the reader stops blocking, whatever woke it.
857 *
858 * @param[in] c the control structure.
859 */
864
865/** Check whether the reader of this control plane is blocked
866 *
867 * Call this after pushing work, to decide whether a signal is needed. The
868 * fence orders the push before the load. See fr_control_sleeping().
869 *
870 * @param[in] c the control structure.
871 * @return
872 * - true if the reader is blocked, and must be signalled.
873 * - false if the reader is running, and will find the work itself.
874 */
880
882{
883 c->same_thread = true;
884 (void) fr_event_fd_delete(c->el, c->fd[0], FR_EVENT_FILTER_IO);
885 close(c->fd[0]);
886 close(c->fd[1]);
887
888 /*
889 * Nothing more to do now that everything is gone.
890 */
891 talloc_set_destructor(c, NULL);
892
893 return 0;
894}
895
896/** Wait for a plane control to become readable
897 *
898 * This is a blocking function so only to be used in rare cases such as waiting
899 * for another thread to complete a task before proceeding.
900 *
901 * @param[in] c the control structure.
902 */
904{
905 struct pollfd fd;
906
907 /*
908 * Senders only wake a reader which announced it is blocking,
909 * and a message may have arrived before we announced.
910 */
911 if (fr_control_sleeping(c)) return;
912
913 fd.fd = c->fd[0];
914 fd.events = POLLIN;
915
916 (void) poll(&fd, 1, -1);
917
919}
bool fr_atomic_queue_mpmc_push(fr_atomic_queue_t *aq, void const *data)
Copy an element into the atomic queue, any number of producers.
fr_atomic_queue_t * fr_atomic_queue_talloc(TALLOC_CTX *ctx, size_t num, size_t elem_len)
Create a fixed-size atomic queue.
bool fr_atomic_queue_spsc_pop(fr_atomic_queue_t *aq, void *data)
Copy an element out of the atomic queue, one consumer only.
Structure to hold the atomic queue.
#define RCSID(id)
Definition build.h:603
#define UNUSED
Definition build.h:415
fr_control_eventset_t
Who defines control plane events.
Definition control.h:62
@ FR_CONTROL_EVENTSET_MAX
Definition control.h:67
void(* fr_control_socket_callback_t)(int sock, fr_time_t now, void *uctx)
A callback for a message which carries a socket.
Definition control.h:53
void(* fr_control_callback_t)(void const *data, size_t data_size, fr_time_t now, void *uctx)
Definition control.h:46
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:194
#define MEM(x)
Definition debug.h:38
#define fr_event_fd_insert(...)
Definition event.h:247
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition event.h:83
fr_atomic_queue_t * aq
the messages, header and data by value.
Definition control.c:217
fr_control_socket_ctx_t * socket_events
callbacks for messages carrying a socket, indexed by event
Definition control.c:203
#define CONTROL_SOCKET_DATAGRAMS
Definition control.c:94
bool fr_control_sleeping(fr_control_t *c)
Record that the reader of this control plane is about to block.
Definition control.c:843
static void control_socket_dgram_size_measure(void)
Measure what one datagram carrying a socket takes up in a socket buffer.
Definition control.c:109
static unsigned int control_service(fr_control_t *c)
Dispatch every queued message.
Definition control.c:274
#define CONTROL_RECV_FLAGS
Definition control.c:182
void fr_control_awake(fr_control_t *c)
Record that the reader of this control plane is running again.
Definition control.c:860
void * uctx
context for the callback
Definition control.c:187
static int _control_free(fr_control_t *c)
Free a control structure.
Definition control.c:400
static void control_socket_dispatch(fr_control_t *c, struct mmsghdr *mmh, fr_control_header_t const *hdr, fr_time_t now)
Dispatch one datagram taken off the wakeup socket.
Definition control.c:300
static int control_pre_event(UNUSED fr_time_t now, UNUSED fr_time_delta_t wake, void *uctx)
Announce that the reader is about to block, and drain the queue one last time.
Definition control.c:375
#define CACHE_LINE_BYTES
Definition control.c:51
bool same_thread
are the two ends in the same thread
Definition control.c:229
fr_event_list_t * el
our event list
Definition control.c:212
fr_control_eventset_table_t eventsets[FR_CONTROL_EVENTSET_MAX]
one table per event set
Definition control.c:235
uint16_t max_size
the largest payload a message may carry.
Definition control.c:215
static void control_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
Take a batch of datagrams off the wakeup socket, then dispatch every queued message.
Definition control.c:341
#define CONTROL_SOCKET_MSGS_PER_READ
Definition control.c:86
bool fr_control_is_sleeping(fr_control_t *c)
Check whether the reader of this control plane is blocked.
Definition control.c:875
uint16_t socket_events_num
the size of the socket callback array
Definition control.c:202
bool opened
has the control path been opened.
Definition control.c:231
fr_control_ctx_t * events
callbacks, indexed by event
Definition control.c:200
uint32_t data_size
size of the data we're sending
Definition control.c:64
int fr_control_open(fr_control_t *c)
Open the control-plane signalling path.
Definition control.c:446
uint16_t slots
messages the queue holds unread.
Definition control.c:214
fr_control_eventset_t es
event set of this message
Definition control.c:62
uint16_t event
event this message signals, within its event set
Definition control.c:63
fr_control_t * fr_control_create(TALLOC_CTX *ctx, fr_event_list_t *el, uint16_t slots, uint16_t max_size)
Create a control-plane signaling path.
Definition control.c:427
int fd[2]
wakeup socketpair.
Definition control.c:226
struct fr_control_s::@54 socket
uint16_t events_num
the size of the callback array
Definition control.c:199
int fr_control_callback_add(fr_control_t *c, fr_control_eventset_t es, uint16_t ev, fr_control_callback_t callback, void *uctx)
Register a callback for a message.
Definition control.c:659
fr_control_callback_t callback
the function to call
Definition control.c:186
static size_t control_socket_dgram_size_actual
Definition control.c:103
atomic_bool sleeping
the reader is blocked waiting for a signal.
Definition control.c:233
void * uctx
context for the callback
Definition control.c:192
static fr_control_ctx_t const * control_ctx_find(fr_control_t const *c, fr_control_eventset_t es, uint16_t ev)
Find the callback registered for a message.
Definition control.c:247
static size_t control_message_size(fr_control_t const *c)
The size of one queued message: header and the largest payload.
Definition control.c:262
int fr_control_socket_callback_delete(fr_control_t *c, fr_control_eventset_t es, uint16_t ev)
Delete a callback for a message which carries a socket.
Definition control.c:813
int fr_control_socket_send(fr_control_t *c, fr_control_eventset_t es, uint16_t ev, int sock)
Send a control-plane message carrying a socket.
Definition control.c:604
static void control_post_event(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
The reader is running again.
Definition control.c:386
fr_control_socket_callback_t callback
the function to call
Definition control.c:191
int fr_control_callback_delete(fr_control_t *c, fr_control_eventset_t es, uint16_t ev)
Delete a callback for a message.
Definition control.c:786
int fr_control_message_send(fr_control_t *c, fr_control_eventset_t es, uint16_t ev, void const *data, size_t data_size)
Send a control-plane message.
Definition control.c:544
int fr_control_same_thread(fr_control_t *c)
Definition control.c:881
static pthread_once_t control_socket_dgram_size_once
Definition control.c:104
int fr_control_socket_callback_add(fr_control_t *c, fr_control_eventset_t es, uint16_t ev, fr_control_socket_callback_t callback, void *uctx)
Register a callback for a message which carries a socket.
Definition control.c:727
void fr_control_wait(fr_control_t *c)
Wait for a plane control to become readable.
Definition control.c:903
Ancillary data for the one socket a datagram may carry.
Definition control.c:76
The dispatch table for one event set.
Definition control.c:198
The header of every message.
Definition control.c:61
The control structure.
Definition control.c:211
int fr_event_pre_delete(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx)
Delete a pre-event callback from the event list.
Definition event.c:2018
int fr_event_fd_unarmour(fr_event_list_t *el, int fd, fr_event_filter_t filter, uintptr_t armour)
Unarmour an FD.
Definition event.c:1333
int fr_event_post_delete(fr_event_list_t *el, fr_event_post_cb_t callback, void *uctx)
Delete a post-event callback from the event list.
Definition event.c:2066
#define fr_time()
Definition event.c:58
int fr_event_pre_insert(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx)
Add a pre-event callback to the event list.
Definition event.c:1996
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Definition event.c:1204
int fr_event_post_insert(fr_event_list_t *el, fr_event_post_cb_t callback, void *uctx)
Add a post-event callback to the event list.
Definition event.c:2043
int fr_event_fd_armour(fr_event_list_t *el, int fd, fr_event_filter_t filter, uintptr_t armour)
Armour an FD.
Definition event.c:1303
Stores all information relating to an event list.
Definition event.c:375
unsigned short uint16_t
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
int fr_nonblock(UNUSED int fd)
Definition misc.c:293
int fr_cloexec(UNUSED int fd)
Definition misc.c:331
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, UNUSED struct timespec *timeout)
Emulates the real recvmmsg in userland.
Definition missing.c:551
@ memory_order_seq_cst
Definition stdatomic.h:132
#define atomic_load_explicit(object, order)
Definition stdatomic.h:312
#define atomic_thread_fence(order)
Definition stdatomic.h:148
#define atomic_store_explicit(object, desired, order)
Definition stdatomic.h:314
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
static fr_event_list_t * el
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const_push(_msg)
Definition strerror.h:227
#define fr_strerror_const(_msg)
Definition strerror.h:223
static fr_slen_t data
Definition value.h:1366
static fr_sbuff_err_t char size_t * len
Definition value.h:1061