25RCSID(
"$Id: 693d7f9ff179420537b600091c13173c70ef1eda $")
27#include <freeradius-devel/io/channel.h>
28#include <freeradius-devel/util/debug.h>
30#ifdef HAVE_STDATOMIC_H
33# include <freeradius-devel/util/stdatomic.h>
40#define MPRINT(...) fprintf(stdout, __VA_ARGS__)
55size_t channel_direction_len =
NUM_ELEMENTS(channel_direction);
59#define SIGNAL_INTERVAL (1000000)
73#define ATOMIC_QUEUE_SIZE (1024)
249 MPRINT(
"Signalling %s, with %s\n",
257#define RTT(_old, _new) fr_time_delta_wrap((fr_time_delta_unwrap(_new) + (fr_time_delta_unwrap(_old) * (IALPHA - 1))) / IALPHA)
292 cd->live.sequence = sequence;
293 cd->live.ack = requestor->
ack;
316 "Channel data timestamp (%" PRId64
") older than last channel data sent (%" PRId64
")",
331 MPRINT(
"REQUESTOR SKIPS signal\n");
342 MPRINT(
"REQUESTOR SIGNALS\n");
399 requestor->
ack = cd->live.sequence;
436 responder->
ack = cd->live.sequence;
479 cd->live.sequence = sequence;
480 cd->live.ack = responder->
ack;
504 "Channel data timestamp (%" PRId64
") older than last channel data sent (%" PRId64
")",
522 MPRINT(
"\tRESPONDER SKIPS signal\n");
562 if (((responder->
sequence - their_view_of_my_sequence) <= 1000) &&
565 MPRINT(
"\tRESPONDER SKIPS signal\n");
602 memcpy(cc,
data,
sizeof(*cc));
643 MPRINT(
"channel got data_to_responder\n");
659 MPRINT(
"channel got data_to_requestor\n");
680 MPRINT(
"channel got data_done_responder\n");
706 MPRINT(
"REQUESTOR SKIPS signal AFTER data_done_responder num_outstanding %"PRIu64
"\n",
722 MPRINT(
"REQUESTOR SIGNALS AFTER data_done_responder\n");
737 MPRINT(
"channel got open\n");
751 MPRINT(
"channel got close\n");
765 MPRINT(
"channel got close_ack\n");
790 hooks->
cb = *callbacks;
869 if (!active)
return 0;
899 unsigned int num = 0;
924 if (!active)
return 0;
size_t fr_atomic_queue_size(fr_atomic_queue_t *aq)
bool fr_atomic_queue_spsc_push(fr_atomic_queue_t *aq, void const *data)
Copy an element into the atomic queue, one producer only.
fr_atomic_queue_t * fr_atomic_queue_talloc(TALLOC_CTX *ctx, size_t num, size_t elem_len)
Create a fixed-size atomic queue.
bool fr_atomic_queue_spsc_pop(fr_atomic_queue_t *aq, void *data)
Copy an element out of the atomic queue, one consumer only.
Structure to hold the atomic queue.
#define L(_str)
Helper for initialising arrays of string literals.
static void channel_message_unpack(fr_channel_control_t *cc, void const *data, NDEBUG_UNUSED size_t data_size)
Unpack the payload of a channel control message.
fr_atomic_queue_t * aq
The queue of messages - visible only to this channel.
atomic_bool active
Whether the channel is active.
fr_control_t * control
the control plane these were registered on
void * fr_channel_requestor_uctx_get(fr_channel_t *ch)
Get network-specific data from a channel.
uint64_t sequence_at_last_signal
When we last signaled.
fr_channel_stats_t const * fr_channel_responder_stats(fr_channel_t const *ch)
Statistics for the responder's end of a channel.
fr_message_set_t * reply_ms
the reply message set, for open only.
uint64_t sequence
Sequence number for this channel.
fr_table_num_sorted_t const channel_signals[]
static void channel_drain_replies(fr_channel_t *ch)
Drain the replies queued for the requestor.
bool fr_channel_recv_reply(fr_channel_t *ch)
Receive a reply message from the channel.
fr_channel_direction_t direction
Use for debug messages.
unsigned int fr_channel_responder_discard(fr_channel_t *ch)
Discard any requests the requestor queued but we never received.
size_t channel_signals_len
void * uctx
Worker context.
size_t channel_packet_priority_len
int fr_channel_signal_open(fr_channel_t *ch, fr_message_set_t *reply_ms)
Send a channel to a responder.
static void channel_data_done_responder(void const *data, size_t data_size, fr_time_t now, void *uctx)
The responder has serviced its requests, and says how many it has seen.
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.
static int fr_channel_data_ready(fr_channel_t *ch, fr_time_t when, fr_channel_end_t *end, fr_channel_control_event_t ev)
Send a message via a kq user signal.
fr_table_num_sorted_t const channel_packet_priority[]
fr_channel_stats_t const * fr_channel_requestor_stats(fr_channel_t const *ch)
Statistics for the requestor's end of a channel.
static void channel_close_ack(void const *data, size_t data_size, fr_time_t now, void *uctx)
The responder has finished closing a channel we asked it to close.
#define ATOMIC_QUEUE_SIZE
Size of the atomic queues.
int fr_channel_callbacks_add(fr_control_t *c, fr_channel_callbacks_t const *callbacks, void *uctx)
Register the owner's channel callbacks on its control plane.
static void channel_drain_requests(fr_channel_t *ch)
Drain the requests queued for the responder.
fr_channel_stats_t stats
channel statistics
fr_control_t * control
The control plane we signal this end through.
static void channel_open(void const *data, size_t data_size, fr_time_t now, void *uctx)
A requestor has opened a channel to us.
static void channel_close(void const *data, size_t data_size, fr_time_t now, void *uctx)
The requestor is closing a channel to us.
bool same_thread
are both ends in the same thread?
static void channel_data_to_responder(void const *data, size_t data_size, UNUSED fr_time_t now, void *uctx)
The requestor has queued requests for the responder.
int fr_channel_set_recv_reply(fr_channel_t *ch, fr_channel_recv_callback_t recv_reply, void *uctx)
void * uctx
passed to each callback
uint64_t ack
the sender's ack sequence, for data done.
void * fr_channel_responder_uctx_get(fr_channel_t *ch)
Get responder-specific data from a channel.
bool fr_channel_recv_request(fr_channel_t *ch)
Receive a request message from the channel.
int fr_channel_null_reply(fr_channel_t *ch)
Don't send a reply message into the channel.
void fr_channel_requestor_uctx_add(fr_channel_t *ch, void *uctx)
Add network-specific data to a channel.
fr_time_delta_t cpu_time
Total time used by the responder for this channel.
fr_channel_callbacks_t cb
what the owner does with each event
int fr_channel_service_kevent(fr_channel_t *ch, fr_control_t *c, UNUSED struct kevent const *kev)
Service a control-plane event.
void fr_channel_responder_uctx_add(fr_channel_t *ch, void *uctx)
Add responder-specific data to a channel.
int fr_channel_set_recv_request(fr_channel_t *ch, fr_channel_recv_callback_t recv_request, void *uctx)
int fr_channel_send_reply(fr_channel_t *ch, fr_channel_data_t *cd)
Send a reply message into the channel.
static void channel_data_to_requestor(void const *data, size_t data_size, UNUSED fr_time_t now, void *uctx)
The responder has queued replies for the requestor.
fr_channel_end_t end[2]
Two ends of the channel.
void fr_channel_stats_log(fr_channel_t const *ch, fr_log_t const *log, char const *file, int line)
fr_channel_t * ch
the channel
uint64_t their_view_of_my_sequence
Should be clear.
bool fr_channel_active(fr_channel_t *ch)
Check if a channel is active.
fr_time_delta_t processing_time
Time spent by the responder processing requests.
int fr_channel_responder_ack_close(fr_channel_t *ch)
Acknowledge that the channel is closing.
uint64_t ack
Sequence number of the other end.
fr_channel_recv_callback_t recv
callback for receiving messages
void * recv_uctx
context for receiving messages
The payload of every channel control message.
The callbacks one control plane's owner registered for channel events.
A full channel, which consists of two ends.
fr_message_t m
the message header
fr_time_delta_t message_interval
Interval between messages.
uint64_t packets
Number of actual data packets.
fr_channel_control_event_t
Events channels send, in the FR_CONTROL_EVENTSET_CHANNEL event set.
@ FR_CHANNEL_CONTROL_OPEN
A requestor has opened a channel to the responder.
@ FR_CHANNEL_CONTROL_DATA_TO_REQUESTOR
Replies are queued for the requestor.
@ FR_CHANNEL_CONTROL_DATA_DONE_RESPONDER
The responder has serviced its requests, and says how many it has seen.
@ FR_CHANNEL_CONTROL_CLOSE_ACK
The responder has finished closing it.
@ FR_CHANNEL_CONTROL_CLOSE
The requestor is closing the channel.
@ FR_CHANNEL_CONTROL_DATA_TO_RESPONDER
Requests are queued for the responder.
uint64_t resignals
Number of signals resent.
void(* fr_channel_recv_callback_t)(fr_channel_t *ch, fr_channel_data_t *cd, void *uctx)
uint64_t outstanding
Number of outstanding requests with no reply.
fr_time_t last_sent_signal
The last time when we signaled the other end.
fr_time_t last_read_other
Last time we successfully read a message from the other the channel.
fr_channel_closed_t closed
fr_time_t last_write
Last write to the channel.
uint64_t kevents
Number of times we've looked at kevents.
uint64_t signals
Number of kevent signals we've sent.
uint64_t spurious
Number of signals we received which found no data waiting.
What the owner of a control plane does with channel lifecycle events.
Channel information which is added to a message.
Statistics for the channel.
@ FR_CONTROL_EVENTSET_CHANNEL
Events channels define.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
bool fr_control_is_sleeping(fr_control_t *c)
Check whether the reader of this control plane is blocked.
int fr_control_callback_add(fr_control_t *c, fr_control_eventset_t es, uint16_t ev, fr_control_callback_t callback, void *uctx)
Register a callback for a message.
int fr_control_message_send(fr_control_t *c, fr_control_eventset_t es, uint16_t ev, void const *data, size_t data_size)
Send a control-plane message.
#define fr_log(_log, _lvl, _file, _line, _fmt,...)
@ L_INFO
Informational message.
int fr_message_done(fr_message_t *m)
Mark a message as done.
A Message set, composed of message headers and ring buffer data.
fr_time_t when
when this message was sent
#define atomic_store(object, desired)
#define atomic_load_explicit(object, order)
#define atomic_load(object)
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
static int64_t fr_time_unwrap(fr_time_t time)
#define fr_time_lteq(_a, _b)
#define fr_time_delta_ispos(_a)
#define fr_time_sub(_a, _b)
Subtract one time from another.
A time delta, a difference in time measured in nanoseconds.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)