23RCSID(
"$Id: aedf40e0eaaacffd6e61ddb46ea0aef37dbf01e0 $")
 
   25#include <freeradius-devel/io/channel.h> 
   26#include <freeradius-devel/io/control.h> 
   27#include <freeradius-devel/util/debug.h> 
   28#include <freeradius-devel/util/syserror.h> 
   29#include <freeradius-devel/util/talloc.h> 
   38#define MAX_MESSAGES            (2048) 
   39#define MAX_CONTROL_PLANE       (1024) 
   40#define MAX_KEVENTS             (10) 
   42#define MPRINT1 if (debug_lvl) printf 
   43#define MPRINT2 if (debug_lvl > 1) printf 
   70        fprintf(stderr, 
"usage: channel_test [OPTS]\n");
 
   71        fprintf(stderr, 
"  -c <control-plane>     Size of the control plane queue.\n");
 
   72        fprintf(stderr, 
"  -m <messages>          Send number of messages.\n");
 
   73        fprintf(stderr, 
"  -o <outstanding>       Keep number of messages outstanding.\n");
 
   74        fprintf(stderr, 
"  -t                     Touch memory for fake packets.\n");
 
   75        fprintf(stderr, 
"  -x                     Debugging mode.\n");
 
 
   82        bool                    running, signaled_close;
 
   83        int                     rcode, i, num_events;
 
   84        int                     num_outstanding, num_messages;
 
   97                fprintf(stderr, 
"Failed creating message set\n");
 
  108                fprintf(stderr, 
"Failed signaling open: %s\n", 
fr_syserror(errno));
 
  115        num_replies = num_outstanding = num_messages = 0;
 
  118        signaled_close = 
false;
 
  132                        MPRINT1(
"Master got reply %d, outstanding=%d, %d/%d sent.\n",
 
  133                                num_replies, num_outstanding, num_messages, 
max_messages);
 
  142                        MPRINT1(
"Master DONE sending\n");
 
  150                MPRINT1(
"Master sending %d messages\n", num_to_send);
 
  152                for (i = 0; i < num_to_send; i++) {
 
  171                        memcpy(cd->
m.
data, &num_messages, 
sizeof(num_messages));
 
  173                        MPRINT1(
"Master sent message %d\n", num_messages);
 
  176                                fprintf(stderr, 
"Failed sending request: %s\n", 
fr_syserror(errno));
 
  182                                MPRINT1(
"Master got reply %d, outstanding=%d, %d/%d sent.\n",
 
  183                                        num_replies, num_outstanding, num_messages, 
max_messages);
 
  193                if (!signaled_close && (num_messages >= 
max_messages) && (num_outstanding == 0)) {
 
  194                        MPRINT1(
"Master signaling worker to exit.\n");
 
  197                                fprintf(stderr, 
"Failed signaling close: %s\n", 
fr_syserror(errno));
 
  201                        signaled_close = 
true;
 
  204                MPRINT1(
"Master waiting on events.\n");
 
  208                MPRINT1(
"Master kevent returned %d\n", num_events);
 
  210                if (num_events < 0) {
 
  211                        if (num_events == EINTR) 
continue;
 
  213                        fprintf(stderr, 
"Failed waiting for kevent: %s\n", 
fr_syserror(errno));
 
  217                if (num_events == 0) 
continue;
 
  222                for (i = 0; i < num_events; i++) {
 
  236                        if (!data_size) 
break;
 
  241                        MPRINT1(
"Master got channel event %d\n", ce);
 
  245                                MPRINT1(
"Master got data ready signal\n");
 
  250                                        MPRINT1(
"Master SIGNAL WITH NO DATA!\n");
 
  257                                        MPRINT1(
"Master got reply %d, outstanding=%d, %d/%d sent.\n",
 
  258                                                num_replies, num_outstanding, num_messages, 
max_messages);
 
  264                                MPRINT1(
"Master received close signal\n");
 
  275                                fprintf(stderr, 
"Master got unexpected CE %d\n", ce);
 
  300        MPRINT2(
"Master messages used = %d\n", rcode);
 
 
  311        int rcode, num_events;
 
  312        int worker_messages = 0;
 
  323                fprintf(stderr, 
"Failed creating message set\n");
 
  327        MPRINT1(
"\tWorker started.\n");
 
  334                MPRINT1(
"\tWorker waiting on events.\n");
 
  337                MPRINT1(
"\tWorker kevent returned %d events\n", num_events);
 
  339                if (num_events < 0) {
 
  340                        if (errno == EINTR) 
continue;
 
  342                        fprintf(stderr, 
"Failed waiting for kevent: %s\n", 
fr_syserror(errno));
 
  346                if (num_events == 0) 
continue;
 
  348                for (i = 0; i < num_events; i++) {
 
  363                        if (!data_size) 
break;
 
  368                        MPRINT1(
"\tWorker got channel event %d\n", ce);
 
  373                                MPRINT1(
"\tWorker received a new channel\n");
 
  378                                MPRINT1(
"\tWorker requested to close the channel.\n");
 
  387                                        MPRINT1(
"\tWorker got message %d\n", worker_messages);
 
  395                                MPRINT1(
"\tWorker got data ready signal\n");
 
  400                                        MPRINT1(
"\tWorker SIGNAL WITH NO DATA!\n");
 
  410                                        memcpy(&message_id, cd->
m.
data, 
sizeof(message_id));
 
  411                                        MPRINT1(
"\tWorker got message %d (says %d)\n", worker_messages, message_id);
 
  422                                                for (j = k = 0; j < reply->
m.
data_size; j++) {
 
  423                                                        k += reply->
m.
data[j];
 
  426                                                reply->
m.
data[4] = k;
 
  430                                        MPRINT1(
"\tWorker sending reply to messages %d\n", worker_messages);
 
  433                                                fprintf(stderr, 
"Failed sending reply: %s\n", 
fr_syserror(errno));
 
  440                                MPRINT1(
"\tWorker got NOOP\n");
 
  445                                fprintf(stderr, 
"\tWorker got unexpected CE %d\n", ce);
 
  461        MPRINT1(
"\tWorker exiting.\n");
 
 
  484int main(
int argc, 
char *argv[])
 
  494        while ((c = getopt(argc, argv, 
"c:hm:o:tx")) != -1) 
switch (c) {
 
  528        argc -= (optind - 1);
 
  529        argv += (optind - 1);
 
  552                fprintf(stderr, 
"channel_test: Failed to create channel\n");
 
  559        (void) pthread_attr_init(&attr);
 
  560        (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
 
  562        (void) pthread_create(&master_id, &attr, 
channel_master, channel);
 
  565        (void) pthread_join(master_id, NULL);
 
  571        fr_channel_debug(channel, stdout);
 
 
fr_atomic_queue_t * fr_atomic_queue_alloc(TALLOC_CTX *ctx, size_t size)
Create fixed-size atomic queue.
Structure to hold the atomic queue.
static TALLOC_CTX * autofree
#define NEVER_RETURNS
Should be placed before the function return type.
bool fr_channel_recv_reply(fr_channel_t *ch)
Receive a reply message from the channel.
int fr_channel_signal_responder_close(fr_channel_t *ch)
Signal a responder that the channel is closing.
int fr_channel_send_request(fr_channel_t *ch, fr_channel_data_t *cd)
Send a request message into the channel.
fr_channel_t * fr_channel_create(TALLOC_CTX *ctx, fr_control_t *requestor, fr_control_t *responder, bool same)
Create a new channel.
fr_channel_event_t fr_channel_service_message(fr_time_t when, fr_channel_t **p_channel, void const *data, size_t data_size)
Service a control-plane message.
bool fr_channel_recv_request(fr_channel_t *ch)
Receive a request message from the channel.
int fr_channel_service_kevent(fr_channel_t *ch, fr_control_t *c, UNUSED struct kevent const *kev)
Service a control-plane event.
int fr_channel_send_reply(fr_channel_t *ch, fr_channel_data_t *cd)
Send a reply message into the channel.
int fr_channel_responder_ack_close(fr_channel_t *ch)
Acknowledge that the channel is closing.
int fr_channel_signal_open(fr_channel_t *ch)
Send a channel to a responder.
A full channel, which consists of two ends.
fr_message_t m
the message header
@ FR_CHANNEL_DATA_READY_REQUESTOR
@ FR_CHANNEL_DATA_READY_RESPONDER
Channel information which is added to a message.
static int max_control_plane
static void * channel_master(void *arg)
int main(int argc, char *argv[])
static void * channel_worker(void *arg)
static fr_atomic_queue_t * aq_master
#define MAX_CONTROL_PLANE
request_t * request_alloc(UNUSED TALLOC_CTX *ctx, UNUSED request_init_args_t const *args)
void request_verify(UNUSED char const *file, UNUSED int line, UNUSED request_t const *request)
static int max_outstanding
static fr_control_t * control_worker
static fr_control_t * control_master
static NEVER_RETURNS void usage(void)
static fr_atomic_queue_t * aq_worker
#define FR_CONTROL_ID_CHANNEL
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
ssize_t fr_control_message_pop(fr_atomic_queue_t *aq, uint32_t *p_id, void *data, size_t data_size)
Pop control-plane message.
fr_control_t * fr_control_create(TALLOC_CTX *ctx, fr_event_list_t *el, fr_atomic_queue_t *aq)
Create a control-plane signaling path.
int fr_message_done(fr_message_t *m)
Mark a message as done.
fr_message_t * fr_message_alloc(fr_message_set_t *ms, fr_message_t *m, size_t actual_packet_size)
Allocate packet data for a message.
int fr_message_set_messages_used(fr_message_set_t *ms)
Count the number of used messages.
void fr_message_set_gc(fr_message_set_t *ms)
Garbage collect the message set.
void fr_message_set_debug(FILE *fp, fr_message_set_t *ms)
Print debug information about the message set.
fr_message_set_t * fr_message_set_create(TALLOC_CTX *ctx, int num_messages, size_t message_size, size_t ring_buffer_size)
Create a message set.
A Message set, composed of message headers and ring buffer data.
fr_time_t when
when this message was sent
uint8_t * data
pointer to the data in the ring buffer
size_t data_size
size of the data in the ring buffer
static fr_event_list_t * events
rlm_rcode_t rcode
Last rcode returned by a module.
Optional arguments for initialising requests.
static _Thread_local int worker_id
Internal ID of the current worker thread.
#define fr_time()
Allow us to arbitrarily manipulate time.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
int fr_time_start(void)
Initialize the local time.