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: 5c072518bef63ddb3a80a010d83c2c095364051f $
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: 5c072518bef63ddb3a80a010d83c2c095364051f $")
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) {
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->request = request;
322 request->async->recv_time = now;
323 request->async->el = el;
324 request->async->packet_ctx = packet_ctx;
325 fr_dlist_entry_init(&request->async->entry);
326}
327
328static inline CC_HINT(always_inline)
330{
331 request->number = atomic_fetch_add_explicit(&request_number, 1, memory_order_seq_cst);
332 if (request->name) talloc_const_free(request->name);
333 request->name = talloc_asprintf(request, "Coord-%s-%"PRIu64, name, request->number);
334}
335
336static int _coord_pair_request_deinit( request_t *request, UNUSED void *uctx)
337{
338 return request_slab_deinit(request);
339}
340
342{
343 request_t *request;
344 fr_coord_packet_ctx_t *packet_ctx;
345
346 request = request_slab_reserve(coord_pair->slab);
347 if (!request) {
348 ERROR("Coordinator failed allocating new request");
349 return NULL;
350 }
351
352 request_slab_element_set_destructor(request, _coord_pair_request_deinit, coord_pair);
353
356 .namespace = virtual_server_dict_by_cs(virtual_server_cs(coord_pair->coord_pair_reg->vs))
357 }))) {
358 ERROR("Coordinator failed initializing new request");
359 request_slab_release(request);
360 return NULL;
361 }
362
363 MEM(packet_ctx = talloc(request, fr_coord_packet_ctx_t));
364 *packet_ctx = (fr_coord_packet_ctx_t) {
365 .coord_pair = coord_pair,
366 .uctx = uctx
367 };
368 coord_pair_request_init(coord_pair->el, request, now, packet_ctx);
369 coord_pair_request_name_number(request, coord_pair->coord_pair_reg->name);
370
371 unlang_interpret_set(request, coord_pair->intp);
372
373 return request;
374}
375
376static void coord_pair_request_start(fr_coord_pair_t *coord_pair, request_t *request, fr_time_t now)
377{
378 fr_pair_t *vp;
379
380 vp = fr_pair_find_by_da(&request->request_pairs, NULL, coord_pair->coord_pair_reg->attr_packet_type);
381 if (!vp) {
382 RERROR("Missing %s attribute", coord_pair->coord_pair_reg->attr_packet_type->name);
383 error:
384 request_slab_release(request);
385 return;
386 }
387
388 request->packet->code = vp->vp_uint32;
389
390 if (virtual_server_push(NULL, request, coord_pair->coord_pair_reg->vs, UNLANG_TOP_FRAME) < 0) {
391 RERROR("Protocol failed to set 'process' function");
392 goto error;
393 }
394
395 if (unlikely(coord_pair_request_time_tracking_start(coord_pair, request, now) < 0)) {
396 RERROR("Failed to start request time tracking");
397 goto error;
398 }
399}
400
401static void _coord_pair_request_internal_init(request_t *request, void *uctx)
402{
403 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
404 fr_time_t now = fr_time();
405
406 fr_assert(request->packet);
407 fr_assert(request->reply);
408
409 request->packet->timestamp = now;
410 request->async = talloc_zero(request, fr_async_t);
411 request->async->request = request;
412 request->async->recv_time = now;
413 request->async->el = coord_pair->el;
414 fr_dlist_entry_init(&request->async->entry);
415
416 /*
417 * Requests generated by the interpreter
418 * are always marked up as internal.
419 */
421 coord_pair_request_time_tracking_start(coord_pair, request, now);
422}
423
424/** External request is now complete - will never happen with coordinators
425 *
426 */
428{
429 fr_assert(0);
430}
431
432/** Internal request (i.e. one generated by the interpreter) is now complete
433 *
434 * Whatever generated the request is now responsible for freeing it.
435 */
436static void _coord_pair_request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, void *uctx)
437{
438 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
439
440 coord_pair_request_time_tracking_end(coord_pair, request, fr_time());
441
442 fr_assert(!fr_heap_entry_inserted(request->runnable));
443 fr_assert(!fr_timer_armed(request->timeout));
444 fr_assert(!fr_dlist_entry_in_list(&request->async->entry));
445}
446
447/** Detached request (i.e. one generated by the interpreter with no parent) is now complete
448 *
449 * As the request has no parent, then there's nothing to free it
450 * so we have to.
451 */
453{
454 fr_assert(!fr_heap_entry_inserted(request->runnable));
455
456 TALLOC_FREE(request->timeout);
457
458 fr_assert(!fr_dlist_entry_in_list(&request->async->entry));
459
460 talloc_free(request);
461}
462
463/** Make us responsible for running the request
464 *
465 */
466static void _coord_pair_request_detach(request_t *request, void *uctx)
467{
468 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
469
470 RDEBUG4("%s - Request detaching", __FUNCTION__);
471
472 if (request_is_detachable(request)) {
473 /*
474 * End the time tracking... We don't track detached requests,
475 * because they don't contribute for the time consumed by an
476 * external request.
477 */
478 if (request->async->tracking.state == FR_TIME_TRACKING_YIELDED) {
479 RDEBUG3("Forcing time tracking to running state, from yielded, for request detach");
480 fr_time_tracking_resume(&request->async->tracking, fr_time());
481 }
482 coord_pair_request_time_tracking_end(coord_pair, request, fr_time());
483
484 if (request_detach(request) < 0) RPEDEBUG("Failed detaching request");
485
486 RDEBUG3("Request is detached");
487 } else {
488 fr_assert_msg(0, "Request is not detachable");
489 }
490}
491
492/** Request is now runnable
493 *
494 */
495static void _coord_pair_request_runnable(request_t *request, void *uctx)
496{
497 fr_coord_pair_t *coord_pair = uctx;
498
499 RDEBUG4("%s - Request marked as runnable", __FUNCTION__);
500 fr_heap_insert(&coord_pair->runnable, request);
501}
502
503/** Interpreter yielded request
504 *
505 */
506static void _coord_pair_request_yield(request_t *request, UNUSED void *uctx)
507{
508 RDEBUG4("%s - Request yielded", __FUNCTION__);
509 if (likely(!request_is_detached(request))) fr_time_tracking_yield(&request->async->tracking, fr_time());
510}
511
512/** Interpreter is starting to work on request again
513 *
514 */
515static void _coord_pair_request_resume(request_t *request, UNUSED void *uctx)
516{
517 RDEBUG4("%s - Request resuming", __FUNCTION__);
518 if (likely(!request_is_detached(request))) fr_time_tracking_resume(&request->async->tracking, fr_time());
519}
520
521/** Check if a request is scheduled
522 *
523 */
524static bool _coord_pair_request_scheduled(request_t const *request, UNUSED void *uctx)
525{
526 return fr_heap_entry_inserted(request->runnable);
527}
528
529/** Update a request's priority
530 *
531 */
532static void _coord_pair_request_prioritise(request_t *request, void *uctx)
533{
534 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
535
536 RDEBUG4("%s - Request priority changed", __FUNCTION__);
537
538 /* Extract the request from the runnable queue _if_ it's in the runnable queue */
539 if (fr_heap_extract(&coord_pair->runnable, request) < 0) return;
540
541 /* Reinsert it to re-evaluate its new priority */
542 fr_heap_insert(&coord_pair->runnable, request);
543}
544
545/** Compare two requests by priority and sequence
546 */
547static fr_cmp_ret_t coord_pair_runnable_cmp(void const *one, void const *two)
548{
549 request_t const *a = one, *b = two;
550 int ret;
551
552 ret = CMP(b->priority, a->priority);
553 if (ret != 0) return ret;
554
555 return CMP(a->sequence, b->sequence);
556}
557
558void fr_coord_pair_inst_destroy(UNUSED fr_coord_t *coord, fr_coord_cb_inst_t *inst, bool single_thread, UNUSED void *uctx) {
559 fr_coord_pair_t *coord_pair = talloc_get_type_abort(inst->inst_data, fr_coord_pair_t);
560 int ret, count = 0;
561
562 if (!single_thread) unlang_interpret_set_thread_default(NULL);
563
564 ret = fr_timer_list_force_run(coord_pair->timeout);
565 if (unlikely(ret < 0)) {
566 fr_assert_msg(0, "Failed to force run the timeout list");
567 } else {
568 count += ret;
569 }
570
571 DEBUG("Coordinator %s is exiting - stopped %u requests", fr_coord_name(coord), count);
572}
573
574/** Create the coord_pair coord instance data
575 */
577 bool single_thread, void *uctx)
578{
579 fr_coord_pair_t *coord_pair;
580 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(uctx, fr_coord_pair_reg_t);
581
582 MEM(coord_pair = talloc(ctx, fr_coord_pair_t));
583 *coord_pair = (fr_coord_pair_t) {
584 .coord = coord,
585 .coord_pair_reg = coord_pair_reg,
586 .el = el
587 };
588
589 coord_pair->runnable = fr_heap_talloc_alloc(coord_pair, coord_pair_runnable_cmp, request_t, runnable, 0);
590 if (!coord_pair->runnable) {
591 fr_strerror_const("Failed creating runnable heap");
592 fail:
593 talloc_free(coord_pair);
594 return NULL;
595 }
596
597 coord_pair->timeout = fr_timer_list_ordered_alloc(coord_pair, el->tl);
598 if (!coord_pair->timeout) {
599 fr_strerror_const("Failed creating timeouts list");
600 goto fail;
601 }
602
603 coord_pair->intp = unlang_interpret_init(coord_pair, el,
605 .init_internal = _coord_pair_request_internal_init,
606
607 .done_external = _coord_pair_request_done_external,
608 .done_internal = _coord_pair_request_done_internal,
609 .done_detached = _coord_pair_request_done_detached,
610
614 .mark_runnable = _coord_pair_request_runnable,
615
618 }, coord_pair);
619
620 if (!coord_pair->intp) goto fail;
621
622 if (!(coord_pair->slab = request_slab_list_alloc(coord_pair, el, &coord_pair_reg->reuse, NULL, NULL,
623 coord_pair, true, false))) {
624 goto fail;
625 }
626
627 if (!single_thread) unlang_interpret_set_thread_default(coord_pair->intp);
628
629 return coord_pair;
630}
631
632static inline CC_HINT(always_inline) void coord_run_request(fr_coord_pair_t *coord_pair, fr_time_t start)
633{
634 request_t *request;
635 fr_time_t now;
636
637 now = start;
638
639 while (fr_time_delta_lt(fr_time_sub(now, start), fr_time_delta_from_msec(1)) &&
640 (fr_heap_pop((void **)&request, &coord_pair->runnable) == 0) && request) {
641 REQUEST_VERIFY(request);
642 fr_assert(!fr_heap_entry_inserted(request->runnable));
643
645
646 now = fr_time();
647 }
648}
649
650/*
651 * Pre and post events used in single threaded mode
652 */
653
655{
656 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
657 request_t *request;
658
659 request = fr_heap_peek(coord_pair->runnable);
660 return request ? 1 : 0;
661}
662
664{
665 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
666
667 coord_run_request(coord_pair, fr_time());
668}
669
670/** Event callback in multi threaded mode
671 */
673{
674 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
675
676 coord_run_request(coord_pair, fr_time());
677}
678
679/** Callback run when a coordinator receives pair list data
680 *
681 * Converts the data into a request.
682 */
684 UNUSED module_ctx_t *mctx, void *inst, void *uctx)
685{
686 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(uctx, fr_coord_pair_reg_t);
687 fr_coord_pair_t *coord_pair = talloc_get_type_abort(inst, fr_coord_pair_t);
688 request_t *request;
689 fr_pair_t *vp;
690
691 request = coord_pair_request_bootstrap(coord_pair, now, coord_pair_reg);
692 if (!request) return;
693
694 if (fr_pair_append_by_da(request->request_ctx, &vp, &request->request_pairs, attr_worker_id) < 0) {
695 error:
696 request_slab_release(request);
697 return;
698 };
699 vp->vp_int32 = worker_id;
700
701 if (fr_internal_decode_list_dbuff(request->pair_list.request, &request->request_pairs,
702 fr_dict_root(request->proto_dict), dbuff, NULL) < 0) {
703 RERROR("Failed decoding packet");
704 goto error;
705 }
706
707 coord_pair_request_start(coord_pair, request, now);
708}
709
710/** Callback run when a worker receives pair list data
711 *
712 * Finds the packet type attribute in the data and calls the callback
713 * registered against the value of that attribute.
714 *
715 * @param cw Worker which received the message.
716 * @param dbuff Data received.
717 * @param now Time the data is received.
718 * @param mctx Module context to pass to callback.
719 * @param uctx The coord_pair registration.
720 */
722{
723 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(uctx, fr_coord_pair_reg_t);
724 fr_pair_list_t list;
725 fr_pair_t *vp;
726
727 fr_pair_list_init(&list);
728 if (fr_internal_decode_list_dbuff(NULL, &list, coord_pair_reg->root, dbuff, NULL) < 0) {
729 PERROR("Failed to decode data as pair list");
730 goto free;
731 }
732
733 vp = fr_pair_find_by_da_nested(&list, NULL, coord_pair_reg->attr_packet_type);
734
735 if (!vp) {
736 ERROR("Message received without %s", coord_pair_reg->attr_packet_type->name);
737 goto free;
738 }
739
740 if (vp->vp_uint32 > coord_pair_reg->max_packet_type || !coord_pair_reg->callbacks[vp->vp_uint32]) {
741 ERROR("Message received with invalid value %pP", vp);
742 goto free;
743 }
744
745 coord_pair_reg->callbacks[vp->vp_uint32]->callback(cw, coord_pair_reg, &list, now, mctx,
746 coord_pair_reg->callbacks[vp->vp_uint32]->uctx);
747
748free:
749 fr_pair_list_free(&list);
750}
751
752/** Send a reply list from a coordinator to a worker
753 *
754 * @param request containing the reply to send.
755 * @param worker_id to send the reply to.
756 * @return
757 * - 0 on success
758 * - -1 on failure
759 */
761{
762 fr_dbuff_t dbuff;
763 fr_dbuff_uctx_talloc_t tctx;
764 fr_coord_packet_ctx_t *packet_ctx = talloc_get_type_abort(request->async->packet_ctx, fr_coord_packet_ctx_t);
765 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(packet_ctx->uctx, fr_coord_pair_reg_t);
766 int ret;
767
768 if (fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, SIZE_MAX) == NULL) return -1;
769 if (fr_internal_encode_list(&dbuff, &request->reply_pairs, NULL) < 0) {
770 fr_dbuff_free_talloc(&dbuff);
771 return -1;
772 }
773
774 ret = fr_coord_to_worker_send(packet_ctx->coord_pair->coord, worker_id, coord_pair_reg->cb_id, &dbuff);
775
776 fr_dbuff_free_talloc(&dbuff);
777
778 return ret;
779}
780
781/** Send a reply list from a coordinator to all workers
782 *
783 * @param request containing the reply to send.
784 * @return
785 * - 0 on success
786 * - < 0 on failure
787 */
789{
790 fr_dbuff_t dbuff;
791 fr_dbuff_uctx_talloc_t tctx;
792 fr_coord_packet_ctx_t *packet_ctx = talloc_get_type_abort(request->async->packet_ctx, fr_coord_packet_ctx_t);
793 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(packet_ctx->uctx, fr_coord_pair_reg_t);
794 int ret;
795
796 if (fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, SIZE_MAX) == NULL) return -1;
797 if (fr_internal_encode_list(&dbuff, &request->reply_pairs, NULL) < 0) {
798 fr_dbuff_free_talloc(&dbuff);
799 return -1;
800 }
801
802 ret = fr_coord_to_worker_broadcast(packet_ctx->coord_pair->coord, coord_pair_reg->cb_id, &dbuff);
803
804 fr_dbuff_free_talloc(&dbuff);
805
806 return ret;
807}
808
809/** Send a pair list from a worker to a coordinator
810 *
811 * The pair list must include an attribute indicating the packet type
812 *
813 * @param cw The coord worker sending the data.
814 * @param coord_pair_reg The coord_pair registration to use.
815 * @param list of pairs to send.
816 * @return
817 * - 0 on success
818 * - -1 on failure
819 */
821{
822 fr_dbuff_t dbuff;
823 fr_dbuff_uctx_talloc_t tctx;
824 int ret;
825
826 if (fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, SIZE_MAX) == NULL) return -1;
827 if (fr_internal_encode_list(&dbuff, list, NULL) < 0) {
828 fr_dbuff_free_talloc(&dbuff);
829 return -1;
830 }
831
832 ret = fr_worker_to_coord_send(cw, coord_pair_reg->cb_id, &dbuff);
833
834 fr_dbuff_free_talloc(&dbuff);
835 return ret;
836}
837
838/** Instance creation called during coordinator creation.
839 *
840 * @param ctx to allocate the instance in.
841 * @param coord Coordinator to create an instance of.
842 * @param el Event list for instance to use.
843 * @param single_thread is the server in single thread mode.
844 * @param uctx configured for the callback this instance relates to.
845 * @return
846 * - fr_coord_cb_inst_t on success
847 * - NULL on failure
848 */
850 bool single_thread, void *uctx)
851{
852 fr_coord_cb_inst_t *cb_inst;
853 fr_coord_pair_t *coord_pair;
854
855 MEM(cb_inst = talloc(ctx, fr_coord_cb_inst_t));
856
857 *cb_inst = (fr_coord_cb_inst_t) {
859 .event_post_cb = fr_coord_pair_post_event,
860 .event_cb = fr_coord_pair_event
861 };
862
863 coord_pair = fr_coord_pair_create(ctx, coord, el, single_thread, uctx);
864 if (!coord_pair) {
865 talloc_free(cb_inst);
866 return NULL;
867 }
868
869 cb_inst->inst_data = coord_pair;
870
871 return cb_inst;
872}
873
874/** Return the coord_pair associated with a coord_pair internal request
875 *
876 * @param request to fetch associated coordinator for.
877 * @return fr_coord_t
878 */
880{
881 fr_coord_packet_ctx_t *packet_ctx = talloc_get_type_abort(request->async->packet_ctx, fr_coord_packet_ctx_t);
882 return packet_ctx->coord_pair;
883}
884
885/** Start a coordinator request to run through a coord_pair process module
886 *
887 * @param coord_pair with the process module to run the request.
888 * @param list Pairs to populate the request.
889 * @param now Request time.
890 * @return
891 * 0 on success
892 * -1 on failure
893 */
895{
896 request_t *request;
897
898 request = coord_pair_request_bootstrap(coord_pair, now, coord_pair->coord_pair_reg);
899 if (!request) return -1;
900
901 fr_pair_list_steal(request->request_ctx, list);
902 fr_pair_list_append(&request->request_pairs, list);
903
904 coord_pair_request_start(coord_pair, request, now);
905 return 0;
906}
#define RCSID(id)
Definition build.h:560
#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:455
#define UNUSED
Definition build.h:384
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1289
#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:1204
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:1597
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1756
#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:725
char const * fr_coord_name(fr_coord_t const *coord)
Return the coordinator name.
Definition coord.c:857
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:782
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:760
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:376
static void _coord_pair_request_resume(request_t *request, UNUSED void *uctx)
Interpreter is starting to work on request again.
Definition coord_pair.c:515
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:329
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:436
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:558
int fr_coord_to_worker_reply_broadcast(request_t *request)
Send a reply list from a coordinator to all workers.
Definition coord_pair.c:788
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:760
static void _coord_pair_request_internal_init(request_t *request, void *uctx)
Definition coord_pair.c:401
static void _coord_pair_request_yield(request_t *request, UNUSED void *uctx)
Interpreter yielded request.
Definition coord_pair.c:506
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:820
static int _coord_pair_request_deinit(request_t *request, UNUSED void *uctx)
Definition coord_pair.c:336
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:721
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:879
static bool _coord_pair_request_scheduled(request_t const *request, UNUSED void *uctx)
Check if a request is scheduled.
Definition coord_pair.c:524
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:672
static fr_cmp_ret_t coord_pair_runnable_cmp(void const *one, void const *two)
Compare two requests by priority and sequence.
Definition coord_pair.c:547
static void _coord_pair_request_detach(request_t *request, void *uctx)
Make us responsible for running the request.
Definition coord_pair.c:466
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 void _coord_pair_request_prioritise(request_t *request, void *uctx)
Update a request's priority.
Definition coord_pair.c:532
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:849
static int fr_coord_pair_pre_event(UNUSED fr_time_t now, UNUSED fr_time_delta_t wake, void *uctx)
Definition coord_pair.c:654
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:452
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:632
fr_event_list_t * el
Event list for interpreter.
Definition coord_pair.c:62
void fr_coord_pair_data_recv(UNUSED fr_coord_t *coord, uint32_t worker_id, fr_dbuff_t *dbuff, fr_time_t now, UNUSED module_ctx_t *mctx, void *inst, void *uctx)
Callback run when a coordinator receives pair list data.
Definition coord_pair.c:683
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:894
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:427
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:576
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
static void fr_coord_pair_post_event(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Definition coord_pair.c:663
static request_t * coord_pair_request_bootstrap(fr_coord_pair_t *coord_pair, fr_time_t now, void *uctx)
Definition coord_pair.c:341
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:495
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:243
#define MEM(x)
Definition debug.h:38
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:3518
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2637
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4926
#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:149
int fr_heap_pop(void **out, fr_heap_t **hp)
Remove a node from the heap.
Definition heap.c:359
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
Definition heap.c:259
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:138
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
Definition heap.h:126
#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:117
The main heap structure.
Definition heap.h:68
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:1302
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
Definition interpret.c:2519
void unlang_interpret_set_thread_default(unlang_interpret_t *intp)
Set the default interpreter for this thread.
Definition interpret.c:2550
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:2478
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1789
#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:116
#define PERROR(_fmt,...)
Definition log.h:233
#define RDEBUG3(fmt,...)
Definition log.h:360
#define RERROR(fmt,...)
Definition log.h:315
#define RPEDEBUG(fmt,...)
Definition log.h:393
#define RDEBUG4(fmt,...)
Definition log.h:361
#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
Minimal data structure to use the new code.
Definition listen.h:63
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
fr_cmp_ret_t
Result of an ordering comparison.
Definition misc.h:50
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
static fr_dict_attr_t const * attr_worker_id
Definition base.c:45
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:385
int request_detach(request_t *child)
Unlink a subrequest from its parent.
Definition request.c:544
#define REQUEST_VERIFY(_x)
Definition request.h:310
#define request_is_detached(_x)
Definition request.h:187
#define request_is_internal(_x)
Definition request.h:186
@ REQUEST_TYPE_INTERNAL
A request generated internally.
Definition request.h:180
#define request_is_detachable(_x)
Definition request.h:188
#define REQUEST_POOL_NUM_OBJECTS
Definition request.h:68
#define request_init(_ctx, _type, _args)
Definition request.h:322
#define REQUEST_POOL_SIZE
Definition request.h:81
Optional arguments for initialising requests.
Definition request.h:288
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:417
@ 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
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:288
#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:1296
int fr_timer_list_force_run(fr_timer_list_t *tl)
Forcibly run all events in an event loop.
Definition timer.c:922
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
static unsigned count
Definition unittest.c:47
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.
fr_dict_t const * virtual_server_dict_by_cs(CONF_SECTION const *cs)
Return the namespace for specified CONF_SECTION.
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_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