The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
coord_pair.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: ec9a7b3c72087b3bf84af340fac59b9f8905dc60 $
19 *
20 * @brief Sending pair lists to and from coordination threads
21 * @file io/coord_pair.c
22 *
23 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
24 */
25RCSID("$Id: ec9a7b3c72087b3bf84af340fac59b9f8905dc60 $")
26
27#include <freeradius-devel/internal/internal.h>
28#include <freeradius-devel/io/listen.h>
29#include <freeradius-devel/io/coord_pair.h>
30#include <freeradius-devel/io/coord_priv.h>
31#include <freeradius-devel/server/main_config.h>
32#include <freeradius-devel/unlang/base.h>
33
34static _Atomic(uint64_t) request_number = 0;
35
38
39static fr_dlist_head_t *coord_pair_regs = NULL;
40static module_list_t *coord_pair_modules;
41static fr_dict_attr_t const *attr_worker_id = NULL;
42
43/** Registration of pair list callbacks
44 *
45 */
46struct fr_coord_pair_reg_s {
47 char const *name; //!< Name for log / request name.
48 fr_dlist_t entry; //!< Entry in list of pair list registrations
49 fr_dict_attr_t const *attr_packet_type; //!< Attribute containing packet type
50 fr_dict_attr_t const *root; //!< Pair list decoding root attribute
51 fr_coord_worker_pair_cb_reg_t **callbacks; //!< Array of pointers to callbacks
52 uint32_t max_packet_type; //!< Largest valid value for packet type
53 uint32_t cb_id; //!< The coordinator callback ID used for pair list handling
54 fr_time_delta_t max_request_time; //!< Maximum time for coordinator request processing.
55 fr_slab_config_t reuse; //!< Request slab allocation config.
56 virtual_server_t const *vs; //!< Virtual server containing coordinator process sections.
57};
58
60 fr_coord_t *coord; //!< Coordinator which this coord pair is attached to.
61 fr_coord_pair_reg_t *coord_pair_reg; //!< Registration details for this coord pair
62 fr_event_list_t *el; //!< Event list for interpreter.
63 unlang_interpret_t *intp; //!< Interpreter for running requests.
64 fr_heap_t *runnable; //!< Current runnable requests.
65
66 fr_timer_list_t *timeout; //!< Track when requests timeout using a dlist.
67 fr_time_delta_t predicted; //!< How long we predict a request will take to execute.
68 fr_time_tracking_t tracking; //!< How much time the coordinator has spent doing things.
69 uint64_t num_active; //!< Number of active requests.
70 request_slab_list_t *slab; //!< slab allocator for request_t
71};
72
73/** Packet context used when coordinator messages are processed through an interpreter
74 *
75 * Allows access to the coordinator structure and arbitrary data
76 * throughout the state machine.
77 */
78typedef struct {
79 fr_coord_pair_t *coord_pair; //!< Coordinator pair this packet is for.
80 void *uctx; //!< Source specific ctx.
82
83/** Conf parser to read slab settings from module config
84 */
89
90/** Remove a coord pair registration from the list when it is freed
91 */
93{
94 fr_assert(coord_pair_regs);
95
96 fr_dlist_remove(coord_pair_regs, to_free);
97
98 /* If all the registrations are gone, free the list */
99 if (fr_dlist_num_elements(coord_pair_regs) == 0) {
100 TALLOC_FREE(coord_pair_regs);
101 TALLOC_FREE(coord_pair_modules);
102 }
103 return 0;
104}
105
106/** Register a set of callbacks for pair list based coordinator messages
107 *
108 * Returns a structure to pass as uctx to fr_coord_cb_t using the
109 * macro FR_COORD_PAIR_CB_CTX_SET.
110 *
111 * @param reg_ctx Callback details to register.
112 */
114{
115 fr_coord_pair_reg_t *coord_pair_reg;
116 fr_coord_worker_pair_cb_reg_t *cb_reg = reg_ctx->worker_cb;
117 CONF_SECTION *cs;
118 CONF_PAIR *cp;
119
120 fr_assert(reg_ctx->root);
121
122 /* Resolve the Worker-Id attribute if not already done */
123 if (!attr_worker_id) {
124 attr_worker_id = fr_dict_attr_by_name(NULL, fr_dict_root(fr_dict_internal()), "Worker-Id");
125 if (!attr_worker_id) {
126 ERROR("Failed to resolve Worker-Id attribute");
127 return NULL;
128 }
129 }
130
131 if (!coord_pair_regs) {
132 MEM(coord_pair_regs = talloc_zero(NULL, fr_dlist_head_t));
133 fr_dlist_init(coord_pair_regs, fr_coord_pair_reg_t, entry);
134 MEM(coord_pair_modules = module_list_alloc(NULL, &module_list_type_global, "coord", true));
135 }
136
137 MEM(coord_pair_reg = talloc(coord_pair_regs, fr_coord_pair_reg_t));
138 *coord_pair_reg = (fr_coord_pair_reg_t) {
139 .name = reg_ctx->name,
140 .root = reg_ctx->root,
141 .cb_id = reg_ctx->cb_id,
142 .max_request_time = fr_time_delta_eq(reg_ctx->max_request_time, fr_time_delta_from_msec(0)) ?
144 };
145
146 while (cb_reg->callback) {
147 if (cb_reg->packet_type > coord_pair_reg->max_packet_type) {
148 coord_pair_reg->max_packet_type = cb_reg->packet_type;
149 }
150 cb_reg++;
151 }
152
153 /*
154 * A sane limit on packet type values to avoid a huge array.
155 * If larger values are needed in the future we can use a folded array.
156 */
157 fr_assert(coord_pair_reg->max_packet_type <= 256);
158
159 MEM(coord_pair_reg->callbacks = talloc_zero_array(coord_pair_reg, fr_coord_worker_pair_cb_reg_t *,
160 coord_pair_reg->max_packet_type + 1));
161
162 cb_reg = reg_ctx->worker_cb;
163 while (cb_reg->callback) {
164 coord_pair_reg->callbacks[cb_reg->packet_type] = cb_reg;
165 cb_reg++;
166 }
167
168 cs = cf_section_find(reg_ctx->cs, "reuse", NULL);
169
170 /*
171 * Create an empty "reuse" section if one is not found, so defaults are applied
172 */
173 if (!cs) {
174 cs = cf_section_alloc(reg_ctx->cs, reg_ctx->cs, "reuse", NULL);
175 }
176
178 fail:
179 talloc_free(coord_pair_reg);
180 return NULL;
181 }
182 if (cf_section_parse(coord_pair_reg, &coord_pair_reg->reuse, cs) < 0) goto fail;
183
184 /*
185 * Set defaults for request slab allocation, if not set by conf parsing
186 */
187 if (!coord_pair_reg->reuse.child_pool_size) coord_pair_reg->reuse.child_pool_size = REQUEST_POOL_SIZE;
188 if (!coord_pair_reg->reuse.num_children) coord_pair_reg->reuse.num_children = REQUEST_POOL_NUM_OBJECTS;
189
190 cp = cf_pair_find(reg_ctx->cs, "virtual_server");
191 if (!cp) {
192 cf_log_err(reg_ctx->cs, "Missing virtual_server option");
193 goto fail;
194 }
195
196 coord_pair_reg->vs = virtual_server_find(cf_pair_value(cp));
197 if (!coord_pair_reg->vs) {
198 cf_log_err(cp, "Virtual server not found");
199 goto fail;
200 }
201
202 /*
203 * Validate that the virtual server uses the correct namespace.
204 */
205 if (reg_ctx->root->dict != virtual_server_dict_by_cs(virtual_server_cs(coord_pair_reg->vs))) {
206 cf_log_err(cp, "Virtual server has namespace %s, should be %s",
207 fr_dict_root(virtual_server_dict_by_cs(virtual_server_cs(coord_pair_reg->vs)))->name,
208 fr_dict_root(coord_pair_reg->root->dict)->name);
209 goto fail;
210 }
211 coord_pair_reg->attr_packet_type = virtual_server_packet_type_by_cs(virtual_server_cs(coord_pair_reg->vs));
212
213 fr_dlist_insert_tail(coord_pair_regs, coord_pair_reg);
214 talloc_set_destructor(coord_pair_reg, _coord_pair_reg_free);
215
216 return coord_pair_reg;
217}
218
219/** Return the coordinator callback ID associated with a coord_pair_reg_t
220 */
222{
223 fr_assert(coord_pair_reg);
224 return coord_pair_reg->cb_id;
225}
226
227/*
228 * The following set of callbacks for request handling are mirrors of
229 * their equivalent in worker.c
230 */
231
232/** Signal the unlang interpreter that it needs to stop running the request
233 *
234 * @param[in] request request to cancel. The request may still run to completion.
235 */
237{
239}
240
241/** Enforce max_request_time
242 *
243 * @param[in] tl the coordinators's timer list.
244 * @param[in] when the current time
245 * @param[in] uctx the request_t timing out.
246 */
248{
249 request_t *request = talloc_get_type_abort(uctx, request_t);
250
251 REDEBUG("Request has reached max_request_time - signalling it to stop");
253
254 request->rcode = RLM_MODULE_TIMEOUT;
255}
256
257/** Set, or re-set the request timer
258 *
259 * @param[in] coord_pair the coord_pair_t containing the timeout lists.
260 * @param[in] request that we're timing out.
261 * @param[in] timeout the timeout to set.
262 * @return
263 * - 0 on success.
264 * - -1 on failure.
265 */
267{
268 if (unlikely(fr_timer_in(request, coord_pair->timeout, &request->timeout, timeout,
269 true, _coord_pair_request_timeout, request) < 0)) {
270 RERROR("Failed to create request timeout timer");
271 return -1;
272 }
273
274 return 0;
275}
276
277/** Start time tracking for a request, and mark it as runnable.
278 */
280{
281 fr_assert(!fr_timer_armed(request->timeout));
282
283 if (unlikely(fr_coord_pair_request_timeout_set(coord_pair, request,
284 coord_pair->coord_pair_reg->max_request_time) < 0)) {
285 RERROR("Failed to set request timeout");
286 return -1;
287 }
288
289 RDEBUG3("Time tracking started in yielded state");
290 fr_time_tracking_start(&coord_pair->tracking, &request->async->tracking, now);
291 fr_time_tracking_yield(&request->async->tracking, now);
292 coord_pair->num_active++;
293
294 fr_assert(!fr_heap_entry_inserted(request->runnable));
295 (void) fr_heap_insert(&coord_pair->runnable, request);
296
297 return 0;
298}
299
300/** End time tracking for a request
301 */
303{
304 RDEBUG3("Time tracking ended");
305 fr_time_tracking_end(&coord_pair->predicted, &request->async->tracking, now);
306 fr_assert(coord_pair->num_active > 0);
307 coord_pair->num_active--;
308
309 TALLOC_FREE(request->timeout); /* Disarm the request timer */
310}
311
312
313static inline CC_HINT(always_inline)
314void coord_pair_request_init(fr_event_list_t *el, request_t *request, fr_time_t now, void *packet_ctx)
315{
316 if (!request->packet) MEM(request->packet = fr_packet_alloc(request, false));
317 if (!request->reply) MEM(request->reply = fr_packet_alloc(request, false));
318
319 request->packet->timestamp = now;
320 request->async = talloc_zero(request, fr_async_t);
321 request->async->recv_time = now;
322 request->async->el = el;
323 request->async->packet_ctx = packet_ctx;
324 fr_dlist_entry_init(&request->async->entry);
325}
326
327static inline CC_HINT(always_inline)
329{
330 request->number = atomic_fetch_add_explicit(&request_number, 1, memory_order_seq_cst);
331 if (request->name) talloc_const_free(request->name);
332 request->name = talloc_asprintf(request, "Coord-%s-%"PRIu64, name, request->number);
333}
334
335static int _coord_pair_request_deinit( request_t *request, UNUSED void *uctx)
336{
337 return request_slab_deinit(request);
338}
339
341{
342 request_t *request;
343 fr_coord_packet_ctx_t *packet_ctx;
344
345 request = request_slab_reserve(coord_pair->slab);
346 if (!request) {
347 ERROR("Coordinator failed allocating new request");
348 return NULL;
349 }
350
351 request_slab_element_set_destructor(request, _coord_pair_request_deinit, coord_pair);
352
355 .namespace = virtual_server_dict_by_cs(virtual_server_cs(coord_pair->coord_pair_reg->vs))
356 }))) {
357 ERROR("Coordinator failed initializing new request");
358 request_slab_release(request);
359 return NULL;
360 }
361
362 MEM(packet_ctx = talloc(request, fr_coord_packet_ctx_t));
363 *packet_ctx = (fr_coord_packet_ctx_t) {
364 .coord_pair = coord_pair,
365 .uctx = uctx
366 };
367 coord_pair_request_init(coord_pair->el, request, now, packet_ctx);
368 coord_pair_request_name_number(request, coord_pair->coord_pair_reg->name);
369
370 unlang_interpret_set(request, coord_pair->intp);
371
372 return request;
373}
374
375static void coord_pair_request_start(fr_coord_pair_t *coord_pair, request_t *request, fr_time_t now)
376{
377 fr_pair_t *vp;
378
379 vp = fr_pair_find_by_da(&request->request_pairs, NULL, coord_pair->coord_pair_reg->attr_packet_type);
380 if (!vp) {
381 RERROR("Missing %s attribute", coord_pair->coord_pair_reg->attr_packet_type->name);
382 error:
383 request_slab_release(request);
384 return;
385 }
386
387 request->packet->code = vp->vp_uint32;
388
389 if (virtual_server_push(NULL, request, coord_pair->coord_pair_reg->vs, UNLANG_TOP_FRAME) < 0) {
390 RERROR("Protocol failed to set 'process' function");
391 goto error;
392 }
393
394 if (unlikely(coord_pair_request_time_tracking_start(coord_pair, request, now) < 0)) {
395 RERROR("Failed to start request time tracking");
396 goto error;
397 }
398}
399
400static void _coord_pair_request_internal_init(request_t *request, void *uctx)
401{
402 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
403 fr_time_t now = fr_time();
404
405 fr_assert(request->packet);
406 fr_assert(request->reply);
407
408 request->packet->timestamp = now;
409 request->async = talloc_zero(request, fr_async_t);
410 request->async->recv_time = now;
411 request->async->el = coord_pair->el;
412 fr_dlist_entry_init(&request->async->entry);
413
414 /*
415 * Requests generated by the interpreter
416 * are always marked up as internal.
417 */
419 coord_pair_request_time_tracking_start(coord_pair, request, now);
420}
421
422/** External request is now complete - will never happen with coordinators
423 *
424 */
426{
427 fr_assert(0);
428}
429
430/** Internal request (i.e. one generated by the interpreter) is now complete
431 *
432 * Whatever generated the request is now responsible for freeing it.
433 */
434static void _coord_pair_request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, void *uctx)
435{
436 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
437
438 coord_pair_request_time_tracking_end(coord_pair, request, fr_time());
439
440 fr_assert(!fr_heap_entry_inserted(request->runnable));
441 fr_assert(!fr_timer_armed(request->timeout));
442 fr_assert(!fr_dlist_entry_in_list(&request->async->entry));
443}
444
445/** Detached request (i.e. one generated by the interpreter with no parent) is now complete
446 *
447 * As the request has no parent, then there's nothing to free it
448 * so we have to.
449 */
451{
452 fr_assert(!fr_heap_entry_inserted(request->runnable));
453
454 TALLOC_FREE(request->timeout);
455
456 fr_assert(!fr_dlist_entry_in_list(&request->async->entry));
457
458 talloc_free(request);
459}
460
461/** Make us responsible for running the request
462 *
463 */
464static void _coord_pair_request_detach(request_t *request, void *uctx)
465{
466 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
467
468 RDEBUG4("%s - Request detaching", __FUNCTION__);
469
470 if (request_is_detachable(request)) {
471 /*
472 * End the time tracking... We don't track detached requests,
473 * because they don't contribute for the time consumed by an
474 * external request.
475 */
476 if (request->async->tracking.state == FR_TIME_TRACKING_YIELDED) {
477 RDEBUG3("Forcing time tracking to running state, from yielded, for request detach");
478 fr_time_tracking_resume(&request->async->tracking, fr_time());
479 }
480 coord_pair_request_time_tracking_end(coord_pair, request, fr_time());
481
482 if (request_detach(request) < 0) RPEDEBUG("Failed detaching request");
483
484 RDEBUG3("Request is detached");
485 } else {
486 fr_assert_msg(0, "Request is not detachable");
487 }
488}
489
490/** Request is now runnable
491 *
492 */
493static void _coord_pair_request_runnable(request_t *request, void *uctx)
494{
495 fr_coord_pair_t *coord_pair = uctx;
496
497 RDEBUG4("%s - Request marked as runnable", __FUNCTION__);
498 fr_heap_insert(&coord_pair->runnable, request);
499}
500
501/** Interpreter yielded request
502 *
503 */
504static void _coord_pair_request_yield(request_t *request, UNUSED void *uctx)
505{
506 RDEBUG4("%s - Request yielded", __FUNCTION__);
507 if (likely(!request_is_detached(request))) fr_time_tracking_yield(&request->async->tracking, fr_time());
508}
509
510/** Interpreter is starting to work on request again
511 *
512 */
513static void _coord_pair_request_resume(request_t *request, UNUSED void *uctx)
514{
515 RDEBUG4("%s - Request resuming", __FUNCTION__);
516 if (likely(!request_is_detached(request))) fr_time_tracking_resume(&request->async->tracking, fr_time());
517}
518
519/** Check if a request is scheduled
520 *
521 */
522static bool _coord_pair_request_scheduled(request_t const *request, UNUSED void *uctx)
523{
524 return fr_heap_entry_inserted(request->runnable);
525}
526
527/** Update a request's priority
528 *
529 */
530static void _coord_pair_request_prioritise(request_t *request, void *uctx)
531{
532 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
533
534 RDEBUG4("%s - Request priority changed", __FUNCTION__);
535
536 /* Extract the request from the runnable queue _if_ it's in the runnable queue */
537 if (fr_heap_extract(&coord_pair->runnable, request) < 0) return;
538
539 /* Reinsert it to re-evaluate its new priority */
540 fr_heap_insert(&coord_pair->runnable, request);
541}
542
543/** Compare two requests by priority and sequence
544 */
545static int8_t coord_pair_runnable_cmp(void const *one, void const *two)
546{
547 request_t const *a = one, *b = two;
548 int ret;
549
550 ret = CMP(b->priority, a->priority);
551 if (ret != 0) return ret;
552
553 return CMP(a->sequence, b->sequence);
554}
555
556void fr_coord_pair_inst_destroy(UNUSED fr_coord_t *coord, fr_coord_cb_inst_t *inst, bool single_thread, UNUSED void *uctx) {
557 fr_coord_pair_t *coord_pair = talloc_get_type_abort(inst->inst_data, fr_coord_pair_t);
558 int ret, count = 0;
559
560 if (!single_thread) unlang_interpret_set_thread_default(NULL);
561
562 ret = fr_timer_list_force_run(coord_pair->timeout);
563 if (unlikely(ret < 0)) {
564 fr_assert_msg(0, "Failed to force run the timeout list");
565 } else {
566 count += ret;
567 }
568
569 DEBUG("Coordinator is exiting - stopped %u requests", count);
570}
571
572/** Create the coord_pair coord instance data
573 */
575 bool single_thread, void *uctx)
576{
577 fr_coord_pair_t *coord_pair;
578 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(uctx, fr_coord_pair_reg_t);
579
580 MEM(coord_pair = talloc(ctx, fr_coord_pair_t));
581 *coord_pair = (fr_coord_pair_t) {
582 .coord = coord,
583 .coord_pair_reg = coord_pair_reg,
584 .el = el
585 };
586
587 coord_pair->runnable = fr_heap_talloc_alloc(coord_pair, coord_pair_runnable_cmp, request_t, runnable, 0);
588 if (!coord_pair->runnable) {
589 fr_strerror_const("Failed creating runnable heap");
590 fail:
591 talloc_free(coord_pair);
592 return NULL;
593 }
594
595 coord_pair->timeout = fr_timer_list_ordered_alloc(coord_pair, el->tl);
596 if (!coord_pair->timeout) {
597 fr_strerror_const("Failed creating timeouts list");
598 goto fail;
599 }
600
601 coord_pair->intp = unlang_interpret_init(coord_pair, el,
603 .init_internal = _coord_pair_request_internal_init,
604
605 .done_external = _coord_pair_request_done_external,
606 .done_internal = _coord_pair_request_done_internal,
607 .done_detached = _coord_pair_request_done_detached,
608
612 .mark_runnable = _coord_pair_request_runnable,
613
616 }, coord_pair);
617
618 if (!coord_pair->intp) goto fail;
619
620 if (!(coord_pair->slab = request_slab_list_alloc(coord_pair, el, &coord_pair_reg->reuse, NULL, NULL,
621 coord_pair, true, false))) {
622 goto fail;
623 }
624
625 if (!single_thread) unlang_interpret_set_thread_default(coord_pair->intp);
626
627 return coord_pair;
628}
629
630static inline CC_HINT(always_inline) void coord_run_request(fr_coord_pair_t *coord_pair, fr_time_t start)
631{
632 request_t *request;
633 fr_time_t now;
634
635 now = start;
636
637 while (fr_time_delta_lt(fr_time_sub(now, start), fr_time_delta_from_msec(1)) &&
638 ((request = fr_heap_pop(&coord_pair->runnable)) != NULL)) {
639 REQUEST_VERIFY(request);
640 fr_assert(!fr_heap_entry_inserted(request->runnable));
641
643
644 now = fr_time();
645 }
646}
647
648/*
649 * Pre and post events used in single threaded mode
650 */
651
653{
654 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
655 request_t *request;
656
657 request = fr_heap_peek(coord_pair->runnable);
658 return request ? 1 : 0;
659}
660
662{
663 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
664
665 coord_run_request(coord_pair, fr_time());
666}
667
668/** Event callback in multi threaded mode
669 */
671{
672 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
673
674 coord_run_request(coord_pair, fr_time());
675}
676
677/** Callback run when a coordinator receives pair list data
678 *
679 * Converts the data into a request.
680 */
682{
683 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(uctx, fr_coord_pair_reg_t);
684 fr_coord_pair_t *coord_pair = talloc_get_type_abort(inst, fr_coord_pair_t);
685 request_t *request;
686 fr_pair_t *vp;
687
688 request = coord_pair_request_bootstrap(coord_pair, now, coord_pair_reg);
689 if (!request) return;
690
691 if (fr_pair_append_by_da(request->request_ctx, &vp, &request->request_pairs, attr_worker_id) < 0) {
692 error:
693 request_slab_release(request);
694 return;
695 };
696 vp->vp_int32 = worker_id;
697
698 if (fr_internal_decode_list_dbuff(request->pair_list.request, &request->request_pairs,
699 fr_dict_root(request->proto_dict), dbuff, NULL) < 0) {
700 RERROR("Failed decoding packet");
701 goto error;
702 }
703
704 coord_pair_request_start(coord_pair, request, now);
705}
706
707/** Callback run when a worker receives pair list data
708 *
709 * Finds the packet type attribute in the data and calls the callback
710 * registered against the value of that attribute.
711 *
712 * @param cw Worker which received the message.
713 * @param dbuff Data received.
714 * @param now Time the data is received.
715 * @param mctx Module context to pass to callback.
716 * @param uctx The coord_pair registration.
717 */
719{
720 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(uctx, fr_coord_pair_reg_t);
721 fr_pair_list_t list;
722 fr_pair_t *vp;
723
724 fr_pair_list_init(&list);
725 if (fr_internal_decode_list_dbuff(NULL, &list, coord_pair_reg->root, dbuff, NULL) < 0) {
726 PERROR("Failed to decode data as pair list");
727 goto free;
728 }
729
730 vp = fr_pair_find_by_da_nested(&list, NULL, coord_pair_reg->attr_packet_type);
731
732 if (!vp) {
733 ERROR("Message received without %s", coord_pair_reg->attr_packet_type->name);
734 goto free;
735 }
736
737 if (vp->vp_uint32 > coord_pair_reg->max_packet_type || !coord_pair_reg->callbacks[vp->vp_uint32]) {
738 ERROR("Message received with invalid value %pP", vp);
739 goto free;
740 }
741
742 coord_pair_reg->callbacks[vp->vp_uint32]->callback(cw, coord_pair_reg, &list, now, mctx,
743 coord_pair_reg->callbacks[vp->vp_uint32]->uctx);
744
745free:
746 fr_pair_list_free(&list);
747}
748
749/** Send a reply list from a coordinator to a worker
750 *
751 * @param request containing the reply to send.
752 * @param worker_id to send the reply to.
753 * @return
754 * - 0 on success
755 * - -1 on failure
756 */
758{
759 fr_dbuff_t dbuff;
760 fr_dbuff_uctx_talloc_t tctx;
761 fr_coord_packet_ctx_t *packet_ctx = talloc_get_type_abort(request->async->packet_ctx, fr_coord_packet_ctx_t);
762 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(packet_ctx->uctx, fr_coord_pair_reg_t);
763 int ret;
764
765 if (fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, SIZE_MAX) == NULL) return -1;
766 if (fr_internal_encode_list(&dbuff, &request->reply_pairs, NULL) < 0) {
767 fr_dbuff_free_talloc(&dbuff);
768 return -1;
769 }
770
771 ret = fr_coord_to_worker_send(packet_ctx->coord_pair->coord, worker_id, coord_pair_reg->cb_id, &dbuff);
772
773 fr_dbuff_free_talloc(&dbuff);
774
775 return ret;
776}
777
778/** Send a reply list from a coordinator to all workers
779 *
780 * @param request containing the reply to send.
781 * @return
782 * - 0 on success
783 * - < 0 on failure
784 */
786{
787 fr_dbuff_t dbuff;
788 fr_dbuff_uctx_talloc_t tctx;
789 fr_coord_packet_ctx_t *packet_ctx = talloc_get_type_abort(request->async->packet_ctx, fr_coord_packet_ctx_t);
790 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(packet_ctx->uctx, fr_coord_pair_reg_t);
791 int ret;
792
793 if (fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, SIZE_MAX) == NULL) return -1;
794 if (fr_internal_encode_list(&dbuff, &request->reply_pairs, NULL) < 0) {
795 fr_dbuff_free_talloc(&dbuff);
796 return -1;
797 }
798
799 ret = fr_coord_to_worker_broadcast(packet_ctx->coord_pair->coord, coord_pair_reg->cb_id, &dbuff);
800
801 fr_dbuff_free_talloc(&dbuff);
802
803 return ret;
804}
805
806/** Send a pair list from a worker to a coordinator
807 *
808 * The pair list must include an attribute indicating the packet type
809 *
810 * @param cw The coord worker sending the data.
811 * @param coord_pair_reg The coord_pair registration to use.
812 * @param list of pairs to send.
813 * @return
814 * - 0 on success
815 * - -1 on failure
816 */
818{
819 fr_dbuff_t dbuff;
820 fr_dbuff_uctx_talloc_t tctx;
821 int ret;
822
823 if (fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, SIZE_MAX) == NULL) return -1;
824 if (fr_internal_encode_list(&dbuff, list, NULL) < 0) {
825 fr_dbuff_free_talloc(&dbuff);
826 return -1;
827 }
828
829 ret = fr_worker_to_coord_send(cw, coord_pair_reg->cb_id, &dbuff);
830
831 fr_dbuff_free_talloc(&dbuff);
832 return ret;
833}
834
835/** Instance creation called during coordinator creation.
836 *
837 * @param ctx to allocate the instance in.
838 * @param coord Coordinator to create an instance of.
839 * @param el Event list for instance to use.
840 * @param single_thread is the server in single thread mode.
841 * @param uctx configured for the callback this instance relates to.
842 * @return
843 * - fr_coord_cb_inst_t on success
844 * - NULL on failure
845 */
847 bool single_thread, void *uctx)
848{
849 fr_coord_cb_inst_t *cb_inst;
850 fr_coord_pair_t *coord_pair;
851
852 MEM(cb_inst = talloc(ctx, fr_coord_cb_inst_t));
853
854 *cb_inst = (fr_coord_cb_inst_t) {
856 .event_post_cb = fr_coord_pair_post_event,
857 .event_cb = fr_coord_pair_event
858 };
859
860 coord_pair = fr_coord_pair_create(ctx, coord, el, single_thread, uctx);
861 if (!coord_pair) {
862 talloc_free(cb_inst);
863 return NULL;
864 }
865
866 cb_inst->inst_data = coord_pair;
867
868 return cb_inst;
869}
870
871/** Return the coord_pair associated with a coord_pair internal request
872 *
873 * @param request to fetch associated coordinator for.
874 * @return fr_coord_t
875 */
877{
878 fr_coord_packet_ctx_t *packet_ctx = talloc_get_type_abort(request->async->packet_ctx, fr_coord_packet_ctx_t);
879 return packet_ctx->coord_pair;
880}
881
882/** Start a coordinator request to run through a coord_pair process module
883 *
884 * @param coord_pair with the process module to run the request.
885 * @param list Pairs to populate the request.
886 * @param now Request time.
887 * @return
888 * 0 on success
889 * -1 on failure
890 */
892{
893 request_t *request;
894
895 request = coord_pair_request_bootstrap(coord_pair, now, coord_pair->coord_pair_reg);
896 if (!request) return -1;
897
898 fr_pair_list_steal(request->request_ctx, list);
899 fr_pair_list_append(&request->request_pairs, list);
900
901 coord_pair_request_start(coord_pair, request, now);
902 return 0;
903}
#define RCSID(id)
Definition build.h:512
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:113
#define unlikely(_x)
Definition build.h:407
#define UNUSED
Definition build.h:336
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1285
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:669
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:701
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:606
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:77
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1194
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1587
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1746
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:345
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:201
int fr_coord_to_worker_send(fr_coord_t *coord, int32_t worker_id, uint32_t cb_id, fr_dbuff_t *dbuff)
Send generic data from a coordinator to a worker.
Definition coord.c:723
int fr_worker_to_coord_send(fr_coord_worker_t *cw, uint32_t cb_id, fr_dbuff_t *dbuff)
Send data from a worker to a coordinator.
Definition coord.c:780
fr_event_list_t * el
Coordinator event list.
Definition coord.c:51
int fr_coord_to_worker_broadcast(fr_coord_t *coord, uint32_t cb_id, fr_dbuff_t *dbuff)
Broadcast data from a coordinator to all workers.
Definition coord.c:758
A coordinator which receives messages from workers.
Definition coord.c:49
The worker end of worker <-> coordinator communication.
Definition coord.c:73
struct fr_coord_cb_inst_s fr_coord_cb_inst_t
Definition coord.h:39
static void coord_pair_request_time_tracking_end(fr_coord_pair_t *coord_pair, request_t *request, fr_time_t now)
End time tracking for a request.
Definition coord_pair.c:302
static int _coord_pair_reg_free(fr_coord_pair_reg_t *to_free)
Remove a coord pair registration from the list when it is freed.
Definition coord_pair.c:92
static void coord_pair_request_start(fr_coord_pair_t *coord_pair, request_t *request, fr_time_t now)
Definition coord_pair.c:375
static void _coord_pair_request_resume(request_t *request, UNUSED void *uctx)
Interpreter is starting to work on request again.
Definition coord_pair.c:513
fr_timer_list_t * timeout
Track when requests timeout using a dlist.
Definition coord_pair.c:66
fr_time_tracking_t tracking
How much time the coordinator has spent doing things.
Definition coord_pair.c:68
static void coord_pair_request_name_number(request_t *request, char const *name)
Definition coord_pair.c:328
static void _coord_pair_request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, void *uctx)
Internal request (i.e.
Definition coord_pair.c:434
fr_coord_pair_reg_t * coord_pair_reg
Registration details for this coord pair.
Definition coord_pair.c:61
void fr_coord_pair_inst_destroy(UNUSED fr_coord_t *coord, fr_coord_cb_inst_t *inst, bool single_thread, UNUSED void *uctx)
Definition coord_pair.c:556
int fr_coord_to_worker_reply_broadcast(request_t *request)
Send a reply list from a coordinator to all workers.
Definition coord_pair.c:785
int fr_coord_to_worker_reply_send(request_t *request, uint32_t worker_id)
Send a reply list from a coordinator to a worker.
Definition coord_pair.c:757
static void _coord_pair_request_internal_init(request_t *request, void *uctx)
Definition coord_pair.c:400
static void _coord_pair_request_yield(request_t *request, UNUSED void *uctx)
Interpreter yielded request.
Definition coord_pair.c:504
int fr_worker_to_coord_pair_send(fr_coord_worker_t *cw, fr_coord_pair_reg_t *coord_pair_reg, fr_pair_list_t *list)
Send a pair list from a worker to a coordinator.
Definition coord_pair.c:817
static int _coord_pair_request_deinit(request_t *request, UNUSED void *uctx)
Definition coord_pair.c:335
fr_time_delta_t predicted
How long we predict a request will take to execute.
Definition coord_pair.c:67
void fr_coord_worker_pair_data_recv(fr_coord_worker_t *cw, fr_dbuff_t *dbuff, fr_time_t now, module_ctx_t *mctx, void *uctx)
Callback run when a worker receives pair list data.
Definition coord_pair.c:718
uint32_t fr_coord_pair_reg_cb_id(fr_coord_pair_reg_t *coord_pair_reg)
Return the coordinator callback ID associated with a coord_pair_reg_t.
Definition coord_pair.c:221
void * uctx
Source specific ctx.
Definition coord_pair.c:80
fr_coord_pair_t * fr_coord_pair_request_coord_pair(request_t *request)
Return the coord_pair associated with a coord_pair internal request.
Definition coord_pair.c:876
static bool _coord_pair_request_scheduled(request_t const *request, UNUSED void *uctx)
Check if a request is scheduled.
Definition coord_pair.c:522
static int coord_pair_request_time_tracking_start(fr_coord_pair_t *coord_pair, request_t *request, fr_time_t now)
Start time tracking for a request, and mark it as runnable.
Definition coord_pair.c:279
fr_coord_t * coord
Coordinator which this coord pair is attached to.
Definition coord_pair.c:60
static void fr_coord_pair_event(UNUSED fr_event_list_t *el, void *uctx)
Event callback in multi threaded mode.
Definition coord_pair.c:670
static void _coord_pair_request_detach(request_t *request, void *uctx)
Make us responsible for running the request.
Definition coord_pair.c:464
fr_coord_pair_t * coord_pair
Coordinator pair this packet is for.
Definition coord_pair.c:79
unlang_interpret_t * intp
Interpreter for running requests.
Definition coord_pair.c:63
static int8_t coord_pair_runnable_cmp(void const *one, void const *two)
Compare two requests by priority and sequence.
Definition coord_pair.c:545
static void _coord_pair_request_prioritise(request_t *request, void *uctx)
Update a request's priority.
Definition coord_pair.c:530
fr_coord_cb_inst_t * fr_coord_pair_inst_create(TALLOC_CTX *ctx, fr_coord_t *coord, fr_event_list_t *el, bool single_thread, void *uctx)
Instance creation called during coordinator creation.
Definition coord_pair.c:846
static int fr_coord_pair_pre_event(UNUSED fr_time_t now, UNUSED fr_time_delta_t wake, void *uctx)
Definition coord_pair.c:652
fr_heap_t * runnable
Current runnable requests.
Definition coord_pair.c:64
static int fr_coord_pair_request_timeout_set(fr_coord_pair_t *coord_pair, request_t *request, fr_time_delta_t timeout)
Set, or re-set the request timer.
Definition coord_pair.c:266
static void _coord_pair_request_done_detached(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
Detached request (i.e.
Definition coord_pair.c:450
static void coord_pair_request_init(fr_event_list_t *el, request_t *request, fr_time_t now, void *packet_ctx)
Definition coord_pair.c:314
static void coord_run_request(fr_coord_pair_t *coord_pair, fr_time_t start)
Definition coord_pair.c:630
fr_event_list_t * el
Event list for interpreter.
Definition coord_pair.c:62
fr_coord_pair_reg_t * fr_coord_pair_register(fr_coord_pair_reg_ctx_t *reg_ctx)
Register a set of callbacks for pair list based coordinator messages.
Definition coord_pair.c:113
int fr_coord_pair_coord_request_start(fr_coord_pair_t *coord_pair, fr_pair_list_t *list, fr_time_t now)
Start a coordinator request to run through a coord_pair process module.
Definition coord_pair.c:891
static void coord_pair_stop_request(request_t *request)
Signal the unlang interpreter that it needs to stop running the request.
Definition coord_pair.c:236
static const conf_parser_t request_reuse_config[]
Conf parser to read slab settings from module config.
Definition coord_pair.c:85
static void _coord_pair_request_done_external(UNUSED request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
External request is now complete - will never happen with coordinators.
Definition coord_pair.c:425
static fr_coord_pair_t * fr_coord_pair_create(TALLOC_CTX *ctx, fr_coord_t *coord, fr_event_list_t *el, bool single_thread, void *uctx)
Create the coord_pair coord instance data.
Definition coord_pair.c:574
static void _coord_pair_request_timeout(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t when, void *uctx)
Enforce max_request_time.
Definition coord_pair.c:247
uint64_t num_active
Number of active requests.
Definition coord_pair.c:69
void fr_coord_pair_data_recv(UNUSED fr_coord_t *coord, uint32_t worker_id, fr_dbuff_t *dbuff, fr_time_t now, void *inst, void *uctx)
Callback run when a coordinator receives pair list data.
Definition coord_pair.c:681
static void fr_coord_pair_post_event(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Definition coord_pair.c:661
static request_t * coord_pair_request_bootstrap(fr_coord_pair_t *coord_pair, fr_time_t now, void *uctx)
Definition coord_pair.c:340
request_slab_list_t * slab
slab allocator for request_t
Definition coord_pair.c:70
static void _coord_pair_request_runnable(request_t *request, void *uctx)
Request is now runnable.
Definition coord_pair.c:493
Packet context used when coordinator messages are processed through an interpreter.
Definition coord_pair.c:78
struct fr_coord_pair_s fr_coord_pair_t
Definition coord_pair.h:33
fr_coord_worker_pair_cb_reg_t * worker_cb
Callbacks for coordinator -> worker pair messages.
Definition coord_pair.h:45
uint32_t packet_type
Packet type value for this callback.
Definition coord_pair.h:38
fr_time_delta_t max_request_time
Maximum time for coordinator request processing.
Definition coord_pair.h:49
fr_dict_attr_t const * root
Root attribute for decoding pair list messages.
Definition coord_pair.h:46
CONF_SECTION * cs
Module conf section.
Definition coord_pair.h:48
char const * name
Name for log entries / request names.
Definition coord_pair.h:44
fr_coord_worker_pair_cb_t callback
Function to call.
Definition coord_pair.h:39
struct fr_coord_pair_reg_s fr_coord_pair_reg_t
Definition coord_pair.h:32
uint32_t cb_id
Coordinator callback id used for pair list messages.
Definition coord_pair.h:47
void * inst_data
Instance data.
Definition coord_priv.h:45
fr_event_status_cb_t event_pre_cb
Pre-event callback in single thread mode.
Definition coord_priv.h:46
static void fr_dbuff_free_talloc(fr_dbuff_t *dbuff)
Free the talloc buffer associated with a dbuff.
Definition dbuff.h:461
static fr_dbuff_t * fr_dbuff_init_talloc(TALLOC_CTX *ctx, fr_dbuff_t *dbuff, fr_dbuff_uctx_talloc_t *tctx, size_t init, size_t max)
Initialise a special dbuff which automatically extends as additional data is written.
Definition dbuff.h:419
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:202
#define MEM(x)
Definition debug.h:36
static fr_dict_attr_t const * attr_packet_type
Definition dhcpclient.c:88
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
Definition dict_util.c:3505
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2639
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4905
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition dlist.h:242
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
Definition dlist.h:620
static bool fr_dlist_entry_in_list(fr_dlist_t const *entry)
Check if a list entry is part of a list.
Definition dlist.h:145
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
Definition dlist.h:921
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Definition dlist.h:360
static void fr_dlist_entry_init(fr_dlist_t *entry)
Initialise a linked list without metadata.
Definition dlist.h:120
Head of a doubly linked list.
Definition dlist.h:51
Entry in a doubly linked list.
Definition dlist.h:41
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
Definition heap.c:146
void * fr_heap_pop(fr_heap_t **hp)
Remove a node from the heap.
Definition heap.c:325
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
Definition heap.c:239
static void * fr_heap_peek(fr_heap_t *h)
Return the item from the top of the heap but don't pop it.
Definition heap.h:136
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
Definition heap.h:124
#define fr_heap_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init)
Creates a heap that verifies elements are of a specific talloc type.
Definition heap.h:115
The main heap structure.
Definition heap.h:66
free(array)
talloc_free(hp)
rlm_rcode_t unlang_interpret(request_t *request, bool running)
Run the interpreter for a current request.
Definition interpret.c:1291
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
Definition interpret.c:2392
void unlang_interpret_set_thread_default(unlang_interpret_t *intp)
Set the default interpreter for this thread.
Definition interpret.c:2423
unlang_interpret_t * unlang_interpret_init(TALLOC_CTX *ctx, fr_event_list_t *el, unlang_request_func_t *funcs, void *uctx)
Initialize a unlang compiler / interpret.
Definition interpret.c:2351
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1771
#define UNLANG_REQUEST_RESUME
Definition interpret.h:48
#define UNLANG_TOP_FRAME
Definition interpret.h:36
External functions provided by the owner of the interpret.
Definition interpret.h:115
Minimal data structure to use the new code.
Definition listen.h:63
#define PERROR(_fmt,...)
Definition log.h:228
#define RDEBUG3(fmt,...)
Definition log.h:355
#define RERROR(fmt,...)
Definition log.h:310
#define RPEDEBUG(fmt,...)
Definition log.h:388
#define RDEBUG4(fmt,...)
Definition log.h:356
#define fr_time()
Definition event.c:60
Stores all information relating to an event list.
Definition event.c:377
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
Definition packet.c:38
main_config_t const * main_config
Main server configuration.
Definition main_config.c:56
fr_worker_config_t worker
Worker thread configuration.
unsigned int uint32_t
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
Definition pair.c:1471
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
Definition pair.c:784
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
void fr_pair_list_steal(TALLOC_CTX *ctx, fr_pair_list_t *list)
Steal a list of pairs to a new context.
Definition pair.c:2307
ssize_t fr_internal_decode_list_dbuff(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *dbuff, void *decode_ctx)
Retrieve all pairs from the dbuff.
Definition decode.c:314
ssize_t fr_internal_encode_list(fr_dbuff_t *dbuff, fr_pair_list_t const *list, void *encode_ctx)
Encode a list of pairs using the internal encoder.
Definition encode.c:304
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:44
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
Definition rcode.h:56
int request_slab_deinit(request_t *request)
Callback for slabs to deinitialise the request.
Definition request.c:383
int request_detach(request_t *child)
Unlink a subrequest from its parent.
Definition request.c:542
#define REQUEST_VERIFY(_x)
Definition request.h:311
#define request_is_detached(_x)
Definition request.h:188
#define request_is_internal(_x)
Definition request.h:187
@ REQUEST_TYPE_INTERNAL
A request generated internally.
Definition request.h:181
#define request_is_detachable(_x)
Definition request.h:189
#define REQUEST_POOL_NUM_OBJECTS
Definition request.h:68
#define request_init(_ctx, _type, _args)
Definition request.h:323
#define REQUEST_POOL_SIZE
Definition request.h:81
Optional arguments for initialising requests.
Definition request.h:289
static char const * name
static _Thread_local int worker_id
Internal ID of the current worker thread.
Definition schedule.c:104
A list of modules.
Definition module.h:407
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
#define FR_SLAB_FUNCS(_name, _type)
Define type specific wrapper functions for slabs and slab elements.
Definition slab.h:124
#define FR_SLAB_TYPES(_name, _type)
Define type specific wrapper structs for slabs and slab elements.
Definition slab.h:75
#define FR_SLAB_CONFIG_CONF_PARSER
conf_parser_t entries to populate user configurable slab values
Definition slab.h:35
Tuneable parameters for slabs.
Definition slab.h:42
module_list_t * module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name, bool write_protect)
Allocate a new module list.
Definition module.c:1898
return count
Definition module.c:155
module_list_type_t const module_list_type_global
Callbacks for a global module list.
Definition module.c:533
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
@ memory_order_seq_cst
Definition stdatomic.h:132
#define atomic_fetch_add_explicit(object, operand, order)
Definition stdatomic.h:302
#define _Atomic(T)
Definition stdatomic.h:77
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:254
#define talloc_asprintf
Definition talloc.h:151
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
Definition time.h:575
#define fr_time_delta_lt(_a, _b)
Definition time.h:285
#define fr_time_delta_eq(_a, _b)
Definition time.h:287
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition time.h:229
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
@ FR_TIME_TRACKING_YIELDED
We're currently tracking time in the yielded state.
static void fr_time_tracking_yield(fr_time_tracking_t *tt, fr_time_t now)
Transition to the yielded state, recording the time we just spent running.
static void fr_time_tracking_end(fr_time_delta_t *predicted, fr_time_tracking_t *tt, fr_time_t now)
End time tracking for this entity.
static void fr_time_tracking_start(fr_time_tracking_t *parent, fr_time_tracking_t *tt, fr_time_t now)
Start time tracking for a tracked entity.
static void fr_time_tracking_resume(fr_time_tracking_t *tt, fr_time_t now)
Track that a request resumed.
fr_timer_list_t * fr_timer_list_ordered_alloc(TALLOC_CTX *ctx, fr_timer_list_t *parent)
Allocate a new sorted event timer list.
Definition timer.c:1290
int fr_timer_list_force_run(fr_timer_list_t *tl)
Forcibly run all events in an event loop.
Definition timer.c:920
An event timer list.
Definition timer.c:49
#define fr_timer_in(...)
Definition timer.h:87
static bool fr_timer_armed(fr_timer_t *ev)
Definition timer.h:120
static fr_event_list_t * el
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
#define fr_strerror_const(_msg)
Definition strerror.h:223
unlang_action_t virtual_server_push(unlang_result_t *p_result, request_t *request, virtual_server_t const *vs, bool top_frame)
Set the request processing function.
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.
fr_dict_t const * virtual_server_dict_by_cs(CONF_SECTION const *server_cs)
Return the namespace for the virtual server specified by a config section.
fr_dict_attr_t const * virtual_server_packet_type_by_cs(CONF_SECTION const *server_cs)
Return the packet type attribute for a virtual server specified by a config section.
fr_time_delta_t max_request_time
maximum time a request can be processed
Definition worker.h:76