The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
proto_load_step.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: d98a1c09729169044641e31b23ccddf0b60c8e55 $
19 * @file proto_load_step.c
20 * @brief Generic protocol load generator
21 *
22 * @copyright 2019 The FreeRADIUS server project.
23 * @copyright 2019 Network RADIUS SAS (legal@networkradius.com)
24 */
25#include <netdb.h>
26#include <fcntl.h>
27#include <freeradius-devel/server/main_loop.h>
28#include <freeradius-devel/io/application.h>
29#include <freeradius-devel/io/listen.h>
30#include <freeradius-devel/io/schedule.h>
31#include <freeradius-devel/io/load.h>
32
33#include "proto_load.h"
34
36
38
39/** What to do when the load test is complete
40 *
41 * The test is complete when the PPS ramp has passed max_pps, all
42 * max_requests packets (if set) have been sent, and every reply has
43 * been received.
44 */
45typedef enum : uint8_t {
46 LOAD_STEP_ON_COMPLETE_EXIT = 0, //!< make the server exit
47 LOAD_STEP_ON_COMPLETE_REPEAT, //!< run the test again from start_pps
48 LOAD_STEP_ON_COMPLETE_STOP, //!< stop generating load, leave the server running
49 LOAD_STEP_ON_COMPLETE_CONTINUE //!< never complete, keep sending at max_pps forever
51
53 { L("continue"), LOAD_STEP_ON_COMPLETE_CONTINUE },
54 { L("exit"), LOAD_STEP_ON_COMPLETE_EXIT },
55 { L("repeat"), LOAD_STEP_ON_COMPLETE_REPEAT },
56 { L("stop"), LOAD_STEP_ON_COMPLETE_STOP }
57};
59
60typedef struct {
61 fr_event_list_t *el; //!< event list
62 fr_network_t *nr; //!< network handler
63
64 char const *name; //!< socket name
65 bool done;
67
68 fr_time_t recv_time; //!< recv time of the last packet
69
71 fr_load_t *l; //!< load generation handler
72 fr_load_config_t load; //!< load configuration
73 fr_stats_t stats; //!< statistics for this socket
74
75 int fd; //!< for CSV files
76 fr_timer_t *ev; //!< for writing statistics
77
78 fr_listen_instance_t *parent; //!< master IO handler
80
83
84 CONF_SECTION *cs; //!< our configuration
85
86 char const *filename; //!< where to read input packet from
87 fr_pair_list_t pair_list; //!< for input packet
88
89 int code;
90 uint32_t max_attributes; //!< Limit maximum decodable attributes
91
92 fr_client_t *client; //!< static client
93
94 fr_load_config_t load; //!< load configuration
95 load_step_on_complete_t on_complete; //!< what to do when the load test completes
96 char const *csv; //!< where to write CSV stats
97
98 fr_dict_t const *dict; //!< Our namespace.
99};
100
101
104 { FR_CONF_OFFSET("csv", proto_load_step_t, csv) },
105
106 { FR_CONF_OFFSET("max_attributes", proto_load_step_t, max_attributes), .dflt = STRINGIFY(RADIUS_MAX_ATTRIBUTES) } ,
107
108 { FR_CONF_OFFSET("start_pps", proto_load_step_t, load.start_pps) },
109 { FR_CONF_OFFSET("max_pps", proto_load_step_t, load.max_pps) },
110 { FR_CONF_OFFSET("duration", proto_load_step_t, load.duration) },
111 { FR_CONF_OFFSET("step", proto_load_step_t, load.step) },
112 { FR_CONF_OFFSET("max_backlog", proto_load_step_t, load.milliseconds) },
113 { FR_CONF_OFFSET("parallel", proto_load_step_t, load.parallel) },
114 { FR_CONF_OFFSET("max_requests", proto_load_step_t, load.max_requests) },
115 { FR_CONF_OFFSET("on_complete", proto_load_step_t, on_complete),
118 .dflt = "exit" },
119
121};
122
123
125 size_t buffer_len, size_t *leftover)
126{
129 proto_load_step_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_load_step_thread_t);
130 fr_io_address_t *address, **address_p;
131
132 if (thread->done) return -1;
133
134 /*
135 * Suspend reading on the FD, because we let the timers
136 * take over the load generation.
137 */
138 if (!thread->suspended) {
139 static fr_event_update_t pause[] = {
142 { 0 }
143 };
144
145 if (fr_event_filter_update(thread->el, li->fd, FR_EVENT_FILTER_IO, pause) < 0) {
146 fr_assert(0);
147 }
148
149 thread->suspended = true;
150
151 /*
152 * If mod_read is first called by an FD read event, then
153 * the sent count will be zero, since the load generator
154 * pre-increments sent.
155 */
156 if (fr_load_generator_stats(thread->l)->sent == 0) return 0;
157 }
158
159 *leftover = 0; /* always for load generation */
160
161 /*
162 * Where the addresses should go. This is a special case
163 * for proto_load.
164 */
165 address_p = (fr_io_address_t **) packet_ctx;
166 address = *address_p;
167
168 memset(address, 0, sizeof(*address));
169 address->socket.inet.src_ipaddr.af = AF_INET;
170 address->socket.inet.dst_ipaddr.af = AF_INET;
171 address->radclient = inst->client;
172
173 *recv_time_p = thread->recv_time;
174
175 if (buffer_len < 1) {
176 DEBUG2("proto_load_step read buffer is too small for input packet");
177 return 0;
178 }
179
180 buffer[0] = 0;
181
182 /*
183 * Print out what we received.
184 */
185 DEBUG2("proto_load_step - reading packet for %s",
186 thread->name);
187
188 return 1;
189}
190
191
192/** The load test is complete - apply on_complete
193 *
194 */
196{
197 fr_load_stats_t const *stats = fr_load_generator_stats(thread->l);
198
199 INFO("Load test for %s complete - sent %d packets, received %d replies",
200 thread->name, stats->sent, stats->received);
201
202 switch (thread->inst->on_complete) {
204 INFO("Signalling the server to exit");
205 thread->done = true;
207 break;
208
210 (void) fr_load_generator_stop(thread->l); /* ensure l->ev is gone */
211 (void) fr_load_generator_start(thread->l);
212 break;
213
215 thread->done = true;
216 break;
217
218 /*
219 * The generator never completes when it's told to
220 * continue forever.
221 */
223 fr_assert(0);
224 break;
225 }
226}
227
228/** The generator noticed completion itself, without a final reply.
229 *
230 */
231static void mod_load_done(void *uctx)
232{
233 fr_listen_instance_t *li = uctx;
234 proto_load_step_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_load_step_thread_t);
235
236 load_complete(thread);
237}
238
241 size_t buffer_len, UNUSED size_t written)
242{
243 proto_load_step_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_load_step_thread_t);
244 fr_load_reply_t state;
245
246 /*
247 * @todo - share a stats interface with the parent? or
248 * put the stats in the listener, so that proto_radius
249 * can update them, too.. <sigh>
250 */
251 thread->stats.total_responses++;
252
253 /*
254 * Tell the load generator subsystem that we have a
255 * reply. If the reply completes the load test, apply
256 * on_complete.
257 */
258 state = fr_load_generator_have_reply(thread->l, request_time);
259 if (state == FR_LOAD_DONE) {
260 load_complete(thread);
261 }
262
263 return buffer_len;
264}
265
266
267/** Open a load listener
268 *
269 */
271{
274 proto_load_step_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_load_step_thread_t);
275
276 fr_ipaddr_t ipaddr;
277
278 /*
279 * We never read or write to this file, but we need a
280 * readable FD in order to bootstrap the process.
281 */
282 li->fd = open(inst->filename, O_RDONLY);
283 if (li->fd < 0) {
284 cf_log_err(li->listen->cs, "Failed opening %s - %s", inst->filename, fr_syserror(errno));
285 return -1;
286 }
287
288 memset(&ipaddr, 0, sizeof(ipaddr));
289 ipaddr.af = AF_INET;
290 li->app_io_addr = fr_socket_addr_alloc_inet_src(li, IPPROTO_UDP, 0, &ipaddr, 0);
291
292 fr_assert((cf_parent(inst->cs) != NULL) && (cf_parent(cf_parent(inst->cs)) != NULL)); /* listen { ... } */
293
294 thread->name = talloc_typed_asprintf(thread, "load_step from filename %s", inst->filename);
295 thread->parent = talloc_parent(li);
296
297 return 0;
298}
299
300
301/** Generate traffic.
302 *
303 */
304static int mod_generate(fr_time_t now, void *uctx)
305{
306 fr_listen_instance_t *li = uctx;
307 proto_load_step_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_load_step_thread_t);
308
309 thread->recv_time = now;
310
311 /*
312 * Tell the network side to call our read routine.
313 */
314 fr_network_listen_read(thread->nr, thread->parent);
315
316 return 0;
317}
318
319
320static void write_stats(fr_timer_list_t *tl, fr_time_t now, void *uctx)
321{
322 proto_load_step_thread_t *thread = uctx;
323 size_t len;
324 char buffer[1024];
325
326 (void) fr_timer_in(thread, tl, &thread->ev, fr_time_delta_from_sec(1), false, write_stats, thread);
327
328 len = fr_load_generator_stats_sprint(thread->l, now, buffer, sizeof(buffer));
329 if (write(thread->fd, buffer, len) < 0) {
330 DEBUG("Failed writing to %s - %s", thread->inst->csv, fr_syserror(errno));
331 }
332}
333
334
335/** Decode the packet
336 *
337 */
338static int mod_decode(void const *instance, request_t *request, UNUSED uint8_t *const data, UNUSED size_t data_len)
339{
341 fr_io_track_t const *track = talloc_get_type_abort_const(request->async->packet_ctx, fr_io_track_t);
342 fr_io_address_t const *address = track->address;
343
344 /*
345 * Hacks for now until we have a lower-level decode routine.
346 */
347 if (inst->code) request->packet->code = inst->code;
348 request->packet->id = fr_rand() & 0xff;
349 request->reply->id = request->packet->id;
350
351 request->packet->data = talloc_zero_array(request->packet, uint8_t, 1);
352 request->packet->data_len = 1;
353
354 (void) fr_pair_list_copy(request->request_ctx, &request->request_pairs, &inst->pair_list);
355
356 /*
357 * Set the rest of the fields.
358 */
359 request->client = UNCONST(fr_client_t *, address->radclient);
360
361 request->packet->socket = address->socket;
362 fr_socket_addr_swap(&request->reply->socket, &address->socket);
363
365
366 return 0;
367}
368
369/** Close a virtual listener
370 *
371 * The fd only exists to bootstrap the listener, so closing it mostly means
372 * removing the timer that drives the load generator.
373 *
374 * @param[in] li the listener
375 * @return
376 * - 0 on success.
377 * - -1 if the generator could not be stopped. The fd is closed either way.
378 */
380{
381 proto_load_step_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_load_step_thread_t);
382 int ret = 0;
383
384 if (thread->l && (fr_load_generator_stop(thread->l) < 0)) {
385 PERROR("Failed stopping load generator");
386 ret = -1;
387 }
388
389 close(li->fd);
390
391 return ret;
392}
393
394/** Set the event list for a new socket
395 *
396 * @param[in] li the listener
397 * @param[in] el the event list
398 * @param[in] nr context from the network side
399 */
401{
404 proto_load_step_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_load_step_thread_t);
405 size_t len;
406 char buffer[256];
407
408 thread->el = el;
409 thread->nr = nr;
410 thread->inst = inst;
411 thread->load = inst->load;
412
413 thread->l = fr_load_generator_create(thread, el, &thread->load, mod_generate, mod_load_done, li);
414 if (!thread->l) return;
415
416 (void) fr_load_generator_start(thread->l);
417
418 if (!inst->csv) return;
419
420 thread->fd = open(inst->csv, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
421 if (thread->fd < 0) {
422 ERROR("Failed opening %s - %s", inst->csv, fr_syserror(errno));
423 return;
424 }
425
426 (void) fr_timer_in(thread, thread->el->tl, &thread->ev, fr_time_delta_from_sec(1), false, write_stats, thread);
427
429 if (write(thread->fd, buffer, len) < 0) {
430 DEBUG("Failed writing to %s - %s", thread->inst->csv, fr_syserror(errno));
431 }
432}
433
434static char const *mod_name(fr_listen_instance_t *li)
435{
436 proto_load_step_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_load_step_thread_t);
437
438 return thread->name;
439}
440
441static int mod_instantiate(module_inst_ctx_t const *mctx)
442{
443 proto_load_step_t *inst = talloc_get_type_abort(mctx->mi->data, proto_load_step_t);
444 CONF_SECTION *conf = mctx->mi->conf;
445 fr_client_t *client;
446 fr_pair_t *vp;
447 module_instance_t const *mi = mctx->mi;
448
450 if (!inst->dict) {
451 cf_log_err(conf, "Please define 'namespace' in this virtual server");
452 return -1;
453 }
454
455 fr_pair_list_init(&inst->pair_list);
456 MEM(inst->client = client = talloc_zero(inst, fr_client_t));
457
458 client->ipaddr.af = AF_INET;
459 client->src_ipaddr = client->ipaddr;
460
461 client->longname = client->shortname = inst->filename;
462 client->secret = talloc_strdup(client, "testing123");
463 client->nas_type = talloc_strdup(client, "load");
464 client->use_connected = false;
465
466 if (inst->filename) {
467 FILE *fp;
468 bool done = false;
469
470 fp = fopen(inst->filename, "r");
471 if (!fp) {
472 cf_log_err(conf, "Failed opening %s - %s",
473 inst->filename, fr_syserror(errno));
474 return -1;
475 }
476
477 if (fr_pair_list_afrom_file(inst, inst->dict, &inst->pair_list, fp, &done, true) < 0) {
478 cf_log_perr(conf, "Failed reading %s", inst->filename);
479 fclose(fp);
480 return -1;
481 }
482
483 fclose(fp);
484 }
485
486 inst->parent = talloc_get_type_abort(mi->parent->data, proto_load_t);
487 inst->cs = conf;
488
489 vp = fr_pair_find_by_da(&inst->pair_list, NULL, inst->parent->attr_packet_type);
490 if (vp) inst->code = vp->vp_uint32;
491
492 FR_INTEGER_BOUND_CHECK("start_pps", inst->load.start_pps, >=, 10);
493 FR_INTEGER_BOUND_CHECK("start_pps", inst->load.start_pps, <, 400000);
494
495 FR_INTEGER_BOUND_CHECK("step", inst->load.step, >=, 1);
496 FR_INTEGER_BOUND_CHECK("step", inst->load.step, <, 100000);
497
498 if (inst->load.max_pps > 0) FR_INTEGER_BOUND_CHECK("max_pps", inst->load.max_pps, >, inst->load.start_pps);
499 FR_INTEGER_BOUND_CHECK("max_pps", inst->load.max_pps, <, 400000);
500
501 FR_TIME_DELTA_BOUND_CHECK("duration", inst->load.duration, >=, fr_time_delta_from_sec(1));
502 FR_TIME_DELTA_BOUND_CHECK("duration", inst->load.duration, <, fr_time_delta_from_sec(10000));
503
504
505 FR_INTEGER_BOUND_CHECK("parallel", inst->load.parallel, >=, 1);
506 FR_INTEGER_BOUND_CHECK("parallel", inst->load.parallel, <, 1000);
507
508 FR_INTEGER_BOUND_CHECK("max_backlog", inst->load.milliseconds, >=, 1);
509 FR_INTEGER_BOUND_CHECK("max_backlog", inst->load.milliseconds, <, 100000);
510
511 /*
512 * "continue" means the test never completes, which
513 * contradicts a finite request count.
514 */
515 if (inst->load.max_requests && (inst->on_complete == LOAD_STEP_ON_COMPLETE_CONTINUE)) {
516 cf_log_err(conf, "'max_requests' cannot be used with 'on_complete = continue'");
517 return -1;
518 }
519
520 inst->load.unlimited = (inst->on_complete == LOAD_STEP_ON_COMPLETE_CONTINUE);
521
522 return 0;
523}
524
532
534 .common = {
535 .magic = MODULE_MAGIC_INIT,
536 .name = "load_step",
538 .inst_size = sizeof(proto_load_step_t),
539 .thread_inst_size = sizeof(proto_load_step_thread_t),
540 .instantiate = mod_instantiate
541 },
542 .default_message_size = 4096,
543 .track_duplicates = false,
544
545 .open = mod_open,
546 .close = mod_close,
547 .read = mod_read,
548 .write = mod_write,
549 .event_list_set = mod_event_list_set,
550 .client_find = mod_client_find,
551 .get_name = mod_name,
552
553 .decode = mod_decode,
554};
static int const char char buffer[256]
Definition acutest.h:641
module_t common
Common fields to all loadable modules.
Definition app_io.h:34
Public structure describing an I/O path for a protocol.
Definition app_io.h:33
#define load(_var)
static int packet_ctx
the tests pass only the address of packet_ctx
static uint8_t request[4]
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:203
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:245
#define STRINGIFY(x)
Definition build.h:233
#define UNUSED
Definition build.h:415
#define NUM_ELEMENTS(_t)
Definition build.h:437
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:722
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:666
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:572
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:280
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:466
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:484
@ CONF_FLAG_FILE_READABLE
File matching value must exist, and must be readable.
Definition cf_parse.h:472
int cf_table_parse_uint8(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:268
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:583
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:649
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition cf_util.c:725
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:340
#define cf_parent(_cf)
Definition cf_util.h:115
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:347
#define MEM(x)
Definition debug.h:38
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
#define fr_event_filter_update(...)
Definition event.h:239
#define FR_EVENT_SUSPEND(_s, _f)
Temporarily remove the filter for a func from kevent.
Definition event.h:115
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition event.h:83
Callbacks for the FR_EVENT_FILTER_IO filter.
Definition event.h:188
Structure describing a modification to a filter's state.
Definition event.h:96
int af
Address family.
Definition inet.h:64
IPv4/6 prefix.
fr_socket_t socket
src/dst ip and port.
Definition base.h:342
fr_client_t const * radclient
old-style client definition
Definition base.h:344
void fr_network_listen_read(fr_network_t *nr, fr_listen_instance_t *li)
Signal the network to read from a listener.
Definition network.c:287
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition client.h:83
char const * secret
Secret PSK.
Definition client.h:90
fr_ipaddr_t src_ipaddr
IPv4/IPv6 address to send responses from (family must match ipaddr).
Definition client.h:84
char const * nas_type
Type of client (arbitrary).
Definition client.h:125
char const * longname
Client identifier.
Definition client.h:87
char const * shortname
Client nickname.
Definition client.h:88
bool use_connected
do we use connected sockets for this client
Definition client.h:115
Describes a host allowed to send packets to the server.
Definition client.h:80
#define PERROR(_fmt,...)
Definition log.h:233
uint64_t total_responses
Definition stats.h:38
#define fr_time()
Definition event.c:58
Stores all information relating to an event list.
Definition event.c:375
fr_listen_t * listen
the listener this is a socket of.
Definition listen.h:65
int fd
file descriptor for this socket - set by open
Definition listen.h:67
void const * app_io_instance
I/O path configuration context.
Definition listen.h:34
CONF_SECTION * cs
of this listener
Definition listen.h:39
fr_socket_t * app_io_addr
for tracking duplicate sockets
Definition listen.h:71
void * thread_instance
thread / socket context
Definition listen.h:69
fr_load_stats_t const * fr_load_generator_stats(fr_load_t const *l)
Definition load.c:452
int fr_load_generator_start(fr_load_t *l)
Start the load generator.
Definition load.c:277
int fr_load_generator_stop(fr_load_t *l)
Stop the load generation through the simple expedient of deleting the timer associated with it.
Definition load.c:312
fr_load_t * fr_load_generator_create(TALLOC_CTX *ctx, fr_event_list_t *el, fr_load_config_t *config, fr_load_callback_t callback, fr_load_done_callback_t done, void *uctx)
Definition load.c:90
size_t fr_load_generator_stats_sprint(fr_load_t *l, fr_time_t now, char *buffer, size_t buflen)
Print load generator statistics in CVS format.
Definition load.c:406
fr_load_reply_t fr_load_generator_have_reply(fr_load_t *l, fr_time_t request_time)
Tell the load generator that we have a reply to a packet we sent.
Definition load.c:324
int sent
total packets sent
Definition load.h:104
int received
total packets received (should be == sent)
Definition load.h:105
fr_load_reply_t
Whether or not the application should continue.
Definition load.h:118
@ FR_LOAD_DONE
the load generator is done
Definition load.h:120
Load generation configuration.
Definition load.h:85
void main_loop_signal_raise(int flag)
Definition main_loop.c:78
@ RADIUS_SIGNAL_SELF_TERM
Definition main_loop.h:37
fr_io_address_t const * address
of this packet.. shared between multiple packets
Definition master.h:55
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
int fr_pair_list_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from)
Duplicate a list of pairs.
Definition pair.c:2312
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:716
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:47
int fr_pair_list_afrom_file(TALLOC_CTX *ctx, fr_dict_t const *dict, fr_pair_list_t *out, FILE *fp, bool *pfiledone, bool allow_exec)
Read valuepairs from the fp up to End-Of-File.
Load master protocol handler.
fr_app_io_t proto_load_step
fr_timer_t * ev
for writing statistics
fr_client_t * client
static client
fr_pair_list_t pair_list
for input packet
fr_load_config_t load
load configuration
static const conf_parser_t load_listen_config[]
CONF_SECTION * cs
our configuration
fr_listen_instance_t * parent
master IO handler
proto_load_step_t const * inst
static int mod_decode(void const *instance, request_t *request, UNUSED uint8_t *const data, UNUSED size_t data_len)
Decode the packet.
static fr_client_t * mod_client_find(fr_listen_instance_t *li, UNUSED fr_ipaddr_t const *ipaddr, UNUSED int ipproto)
fr_load_config_t load
load configuration
char const * filename
where to read input packet from
uint32_t max_attributes
Limit maximum decodable attributes.
struct proto_load_step_s proto_load_step_t
static size_t load_on_complete_table_len
static fr_table_num_sorted_t const load_on_complete_table[]
static int mod_open(fr_listen_instance_t *li)
Open a load listener.
static ssize_t mod_write(fr_listen_instance_t *li, UNUSED void *packet_ctx, fr_time_t request_time, UNUSED uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
char const * csv
where to write CSV stats
static int mod_close(fr_listen_instance_t *li)
Close a virtual listener.
fr_stats_t stats
statistics for this socket
fr_time_t recv_time
recv time of the last packet
fr_load_t * l
load generation handler
static ssize_t mod_read(fr_listen_instance_t *li, void **packet_ctx, fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len, size_t *leftover)
static void mod_event_list_set(fr_listen_instance_t *li, fr_event_list_t *el, void *nr)
Set the event list for a new socket.
static void mod_load_done(void *uctx)
The generator noticed completion itself, without a final reply.
static char const * mod_name(fr_listen_instance_t *li)
load_step_on_complete_t
What to do when the load test is complete.
@ LOAD_STEP_ON_COMPLETE_REPEAT
run the test again from start_pps
@ LOAD_STEP_ON_COMPLETE_STOP
stop generating load, leave the server running
@ LOAD_STEP_ON_COMPLETE_EXIT
make the server exit
@ LOAD_STEP_ON_COMPLETE_CONTINUE
never complete, keep sending at max_pps forever
static void load_complete(proto_load_step_thread_t *thread)
The load test is complete - apply on_complete.
fr_dict_t const * dict
Our namespace.
fr_network_t * nr
network handler
static int mod_generate(fr_time_t now, void *uctx)
Generate traffic.
load_step_on_complete_t on_complete
what to do when the load test completes
fr_event_list_t * el
event list
static int mod_instantiate(module_inst_ctx_t const *mctx)
char const * name
socket name
static void write_stats(fr_timer_list_t *tl, fr_time_t now, void *uctx)
proto_load_t * parent
#define fr_assert(_expr)
Definition rad_assert.h:37
#define DEBUG2(fmt,...)
static bool done
Definition radclient.c:80
static int ipproto
Definition radclient.c:91
#define INFO(fmt,...)
Definition radict.c:67
#define RADIUS_MAX_ATTRIBUTES
Definition radius.h:39
static rs_t * conf
Definition radsniff.c:52
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:128
#define REQUEST_VERIFY(_x)
Definition request.h:310
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:355
void * data
Module's instance data.
Definition module.h:297
module_instance_t const * parent
Parent module's instance (if any).
Definition module.h:363
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:207
Module instance data.
Definition module.h:291
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:621
#define talloc_get_type_abort_const
Definition talloc.h:117
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:599
"server local" time.
Definition time.h:69
An event timer list.
Definition timer.c:49
A timer event.
Definition timer.c:83
#define fr_timer_in(...)
Definition timer.h:87
static fr_event_list_t * el
static fr_socket_t * fr_socket_addr_alloc_inet_src(TALLOC_CTX *ctx, int proto, int ifindex, fr_ipaddr_t const *ipaddr, int port)
A variant of fr_socket_addr_init_inet_src will also allocates a fr_socket_t.
Definition socket.h:249
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition socket.h:83
static void fr_socket_addr_swap(fr_socket_t *dst, fr_socket_t const *src)
Swap src/dst information of a fr_socket_t.
Definition socket.h:126
static fr_slen_t data
Definition value.h:1366
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
fr_dict_t const * virtual_server_dict_by_child_ci(CONF_ITEM const *ci)
Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server.