The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
channel.c File Reference

Two-way thread-safe channels. More...

#include <freeradius-devel/io/channel.h>
#include <freeradius-devel/io/control.h>
#include <freeradius-devel/util/log.h>
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/stdatomic.h>
+ Include dependency graph for channel.c:

Go to the source code of this file.

Data Structures

struct  fr_channel_control_t
 
struct  fr_channel_end_t
 One end of a channel. More...
 
struct  fr_channel_s
 A full channel, which consists of two ends. More...
 

Macros

#define ATOMIC_QUEUE_SIZE   (1024)
 Size of the atomic queues. More...
 
#define ENABLE_SKIPS   (0)
 
#define IALPHA   (8)
 
#define MPRINT(...)
 
#define RTT(_old, _new)   fr_time_delta_wrap((fr_time_delta_unwrap(_new) + (fr_time_delta_unwrap(_old) * (IALPHA - 1))) / IALPHA)
 

Typedefs

typedef enum fr_channel_signal_t fr_channel_signal_t
 
typedef struct fr_channel_s fr_channel_t
 

Enumerations

enum  fr_channel_direction_t {
  TO_RESPONDER = 0 ,
  TO_REQUESTOR = 1
}
 
enum  fr_channel_signal_t {
  FR_CHANNEL_SIGNAL_ERROR = FR_CHANNEL_ERROR ,
  FR_CHANNEL_SIGNAL_DATA_TO_RESPONDER = FR_CHANNEL_DATA_READY_RESPONDER ,
  FR_CHANNEL_SIGNAL_DATA_TO_REQUESTOR = FR_CHANNEL_DATA_READY_REQUESTOR ,
  FR_CHANNEL_SIGNAL_OPEN = FR_CHANNEL_OPEN ,
  FR_CHANNEL_SIGNAL_CLOSE = FR_CHANNEL_CLOSE ,
  FR_CHANNEL_SIGNAL_DATA_DONE_RESPONDER ,
  FR_CHANNEL_SIGNAL_RESPONDER_SLEEPING
}
 

Functions

bool fr_channel_active (fr_channel_t *ch)
 Check if a channel is active. More...
 
fr_channel_tfr_channel_create (TALLOC_CTX *ctx, fr_control_t *requestor, fr_control_t *responder, bool same)
 Create a new channel. More...
 
static int fr_channel_data_ready (fr_channel_t *ch, fr_time_t when, fr_channel_end_t *end, fr_channel_signal_t which)
 Send a message via a kq user signal. More...
 
int fr_channel_null_reply (fr_channel_t *ch)
 Don't send a reply message into the channel. More...
 
bool fr_channel_recv_reply (fr_channel_t *ch)
 Receive a reply message from the channel. More...
 
bool fr_channel_recv_request (fr_channel_t *ch)
 Receive a request message from the channel. More...
 
void fr_channel_requestor_uctx_add (fr_channel_t *ch, void *uctx)
 Add network-specific data to a channel. More...
 
void * fr_channel_requestor_uctx_get (fr_channel_t *ch)
 Get network-specific data from a channel. More...
 
int fr_channel_responder_ack_close (fr_channel_t *ch)
 Acknowledge that the channel is closing. More...
 
int fr_channel_responder_sleeping (fr_channel_t *ch)
 Signal a channel that the responder is sleeping. More...
 
void fr_channel_responder_uctx_add (fr_channel_t *ch, void *uctx)
 Add responder-specific data to a channel. More...
 
void * fr_channel_responder_uctx_get (fr_channel_t *ch)
 Get responder-specific data from a channel. More...
 
int fr_channel_send_reply (fr_channel_t *ch, fr_channel_data_t *cd)
 Send a reply message into the channel. More...
 
int fr_channel_send_request (fr_channel_t *ch, fr_channel_data_t *cd)
 Send a request message into the channel. More...
 
int fr_channel_service_kevent (fr_channel_t *ch, fr_control_t *c, UNUSED struct kevent const *kev)
 Service a control-plane event. More...
 
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. More...
 
int fr_channel_set_recv_reply (fr_channel_t *ch, void *uctx, fr_channel_recv_callback_t recv_reply)
 
int fr_channel_set_recv_request (fr_channel_t *ch, void *uctx, fr_channel_recv_callback_t recv_request)
 
int fr_channel_signal_open (fr_channel_t *ch)
 Send a channel to a responder. More...
 
int fr_channel_signal_responder_close (fr_channel_t *ch)
 Signal a responder that the channel is closing. More...
 
void fr_channel_stats_log (fr_channel_t const *ch, fr_log_t const *log, char const *file, int line)
 

Variables

fr_table_num_sorted_t const channel_packet_priority []
 
size_t channel_packet_priority_len = NUM_ELEMENTS(channel_packet_priority)
 
fr_table_num_sorted_t const channel_signals []
 
size_t channel_signals_len = NUM_ELEMENTS(channel_signals)
 

Detailed Description

Two-way thread-safe channels.

Id
b7df5c377c5e3778bcc5c2b7a7185d59bf6bed06

Definition in file channel.c.


Data Structure Documentation

◆ fr_channel_control_t

struct fr_channel_control_t

Definition at line 97 of file channel.c.

+ Collaboration diagram for fr_channel_control_t:
Data Fields
uint64_t ack or the endpoint..
fr_channel_t * ch the channel
fr_channel_signal_t signal the signal to send

◆ fr_channel_end_t

struct fr_channel_end_t

One end of a channel.

Consists of a kqueue descriptor, and an atomic queue. The atomic queue is there to get bulk data through, because it's more efficient than pushing 1M+ events per second through a kqueue.

Definition at line 109 of file channel.c.

+ Collaboration diagram for fr_channel_end_t:
Data Fields
uint64_t ack Sequence number of the other end.
atomic_bool active Whether the channel is active.
fr_atomic_queue_t * aq The queue of messages - visible only to this channel.
fr_control_t * control The control plane, consisting of an atomic queue and kqueue.
fr_channel_direction_t direction Use for debug messages.
bool must_signal we need to signal the other end
fr_ring_buffer_t * rb Ring buffer for control-plane messages.
fr_channel_recv_callback_t recv callback for receiving messages
void * recv_uctx context for receiving messages
uint64_t sequence Sequence number for this channel.
uint64_t sequence_at_last_signal When we last signaled.
fr_channel_stats_t stats channel statistics
uint64_t their_view_of_my_sequence Should be clear.
void * uctx Worker context.

◆ fr_channel_s

struct fr_channel_s

A full channel, which consists of two ends.

A channel consists of an I/O identifier that can be placed in kequeue and an atomic queue in each direction to allow for bidirectional communication.

Definition at line 144 of file channel.c.

+ Collaboration diagram for fr_channel_s:
Data Fields
fr_time_delta_t cpu_time Total time used by the responder for this channel.
fr_channel_end_t end[2] Two ends of the channel.
fr_time_delta_t processing_time Time spent by the responder processing requests.
bool same_thread are both ends in the same thread?

Macro Definition Documentation

◆ ATOMIC_QUEUE_SIZE

#define ATOMIC_QUEUE_SIZE   (1024)

Size of the atomic queues.

The queue reader MUST service the queue occasionally, otherwise the writer will not be able to write. If it's too low, the writer will fail. If it's too high, it will unnecessarily use memory. So we're better off putting it on the high side.

The reader SHOULD service the queues at inter-packet latency. i.e. at 1M pps, the queue will get serviced every microsecond.

Definition at line 80 of file channel.c.

◆ ENABLE_SKIPS

#define ENABLE_SKIPS   (0)

Definition at line 50 of file channel.c.

◆ IALPHA

#define IALPHA   (8)

Definition at line 291 of file channel.c.

◆ MPRINT

#define MPRINT (   ...)

Definition at line 44 of file channel.c.

◆ RTT

#define RTT (   _old,
  _new 
)    fr_time_delta_wrap((fr_time_delta_unwrap(_new) + (fr_time_delta_unwrap(_old) * (IALPHA - 1))) / IALPHA)

Definition at line 292 of file channel.c.

Typedef Documentation

◆ fr_channel_signal_t

◆ fr_channel_t

typedef struct fr_channel_s fr_channel_t

Definition at line 1 of file channel.c.

Enumeration Type Documentation

◆ fr_channel_direction_t

Enumerator
TO_RESPONDER 
TO_REQUESTOR 

Definition at line 52 of file channel.c.

◆ fr_channel_signal_t

Enumerator
FR_CHANNEL_SIGNAL_ERROR 
FR_CHANNEL_SIGNAL_DATA_TO_RESPONDER 
FR_CHANNEL_SIGNAL_DATA_TO_REQUESTOR 
FR_CHANNEL_SIGNAL_OPEN 
FR_CHANNEL_SIGNAL_CLOSE 
FR_CHANNEL_SIGNAL_DATA_DONE_RESPONDER 
FR_CHANNEL_SIGNAL_RESPONDER_SLEEPING 

Definition at line 82 of file channel.c.

Function Documentation

◆ fr_channel_active()

bool fr_channel_active ( fr_channel_t ch)

Check if a channel is active.

A channel may be closed by either end. If so, it stays alive (but inactive) until both ends acknowledge the close.

Parameters
[in]chthe channel
Returns
  • false the channel is closing.
  • true the channel is active

Definition at line 812 of file channel.c.

+ Here is the caller graph for this function:

◆ fr_channel_create()

fr_channel_t* fr_channel_create ( TALLOC_CTX *  ctx,
fr_control_t requestor,
fr_control_t responder,
bool  same 
)

Create a new channel.

Parameters
[in]ctxThe talloc_ctx to allocate channel data in.
[in]requestorcontrol plane.
[in]respondercontrol plane.
[in]samewhether or not the channel is for the same thread
Returns
  • NULL on error
  • channel on success

Definition at line 183 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_data_ready()

static int fr_channel_data_ready ( fr_channel_t ch,
fr_time_t  when,
fr_channel_end_t end,
fr_channel_signal_t  which 
)
static

Send a message via a kq user signal.

Note that the caller doesn't care about data in the event, that is sent via the atomic queue. The kevent code takes care of delivering the signal once, even if it's sent by multiple requestor threads.

The thread watching the KQ knows which end it is. So when it gets the signal (and the channel pointer) it knows to look at end[0] or end[1]. We also send which end in 'which' (0, 1) to further help the recipient.

Parameters
[in]chthe channel.
[in]whenthe data was ready. Typically taken from the message.
[in]endof the channel that the message was written to.
[in]whichend of the channel (0/1).
Returns
  • <0 on error
  • 0 on success

Definition at line 272 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_null_reply()

int fr_channel_null_reply ( fr_channel_t ch)

Don't send a reply message into the channel.

The message should be the one we received from the network.

Parameters
[in]chthe channel on which we're dropping a packet
Returns
  • <0 on error
  • 0 on success

Definition at line 624 of file channel.c.

+ Here is the caller graph for this function:

◆ fr_channel_recv_reply()

bool fr_channel_recv_reply ( fr_channel_t ch)

Receive a reply message from the channel.

Parameters
[in]chthe channel to read data from.
Returns
  • true if there was a message received
  • false if there are no more messages

Definition at line 408 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_recv_request()

bool fr_channel_recv_request ( fr_channel_t ch)

Receive a request message from the channel.

Parameters
[in]chthe channel
Returns
  • true if there was a message received
  • false if there are no more messages

Definition at line 472 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_requestor_uctx_add()

void fr_channel_requestor_uctx_add ( fr_channel_t ch,
void *  uctx 
)

Add network-specific data to a channel.

Parameters
[in]chThe channel.
[in]uctxThe context to add.

Definition at line 910 of file channel.c.

+ Here is the caller graph for this function:

◆ fr_channel_requestor_uctx_get()

void* fr_channel_requestor_uctx_get ( fr_channel_t ch)

Get network-specific data from a channel.

Parameters
[in]chThe channel.

Definition at line 922 of file channel.c.

+ Here is the caller graph for this function:

◆ fr_channel_responder_ack_close()

int fr_channel_responder_ack_close ( fr_channel_t ch)

Acknowledge that the channel is closing.

Parameters
[in]chThe channel.
Returns
  • <0 on error
  • 0 on success

Definition at line 854 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_responder_sleeping()

int fr_channel_responder_sleeping ( fr_channel_t ch)

Signal a channel that the responder is sleeping.

This function should be called from the responders idle loop. i.e. only when it has nothing else to do.

Parameters
[in]chthe channel to signal we're no longer listening on.
Returns
  • <0 on error
  • 0 on success

Definition at line 646 of file channel.c.

+ Here is the call graph for this function:

◆ fr_channel_responder_uctx_add()

void fr_channel_responder_uctx_add ( fr_channel_t ch,
void *  uctx 
)

Add responder-specific data to a channel.

Parameters
[in]chThe channel.
[in]uctxThe context to add.

Definition at line 885 of file channel.c.

+ Here is the caller graph for this function:

◆ fr_channel_responder_uctx_get()

void* fr_channel_responder_uctx_get ( fr_channel_t ch)

Get responder-specific data from a channel.

Parameters
[in]chThe channel.

Definition at line 897 of file channel.c.

+ Here is the caller graph for this function:

◆ fr_channel_send_reply()

int fr_channel_send_reply ( fr_channel_t ch,
fr_channel_data_t cd 
)

Send a reply message into the channel.

The message should be initialized, other than "sequence" and "ack".

Parameters
[in]chthe channel to send the reply on.
[in]cdthe message to send
Returns
  • <0 on error
  • 0 on success

Definition at line 511 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_send_request()

int fr_channel_send_request ( fr_channel_t ch,
fr_channel_data_t cd 
)

Send a request message into the channel.

The message should be initialized, other than "sequence" and "ack".

This function automatically calls the recv_reply callback if there is a reply.

Parameters
[in]chthe channel to send the request on.
[in]cdthe message to send.
Returns
  • <0 on error
  • 0 on success

Definition at line 306 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_service_kevent()

int fr_channel_service_kevent ( fr_channel_t ch,
fr_control_t c,
UNUSED struct kevent const *  kev 
)

Service a control-plane event.

The channels use control planes for internal signaling. Note that the caller does NOT pass the channel into this function. Instead, the channel is taken from the kevent.

Parameters
[in]chThe channel to service.
[in]cThe control plane on which we received the kev.
[in]kevThe kevent data, should get passed to the control plane.
Returns
  • <0 on error
  • 0 on success

Definition at line 788 of file channel.c.

+ Here is the caller graph for this function:

◆ fr_channel_service_message()

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.

Parameters
[in]whenThe current time.
[out]p_channelThe channel which should be serviced.
[in]dataThe control message.
[in]data_sizeThe size of the control message.
Returns
  • FR_CHANNEL_ERROR on error
  • FR_CHANNEL_NOOP, on do nothing
  • FR_CHANNEL_DATA_READY on data ready
  • FR_CHANNEL_OPEN when a channel has been opened and sent to us
  • FR_CHANNEL_CLOSE when a channel should be closed

Definition at line 685 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_set_recv_reply()

int fr_channel_set_recv_reply ( fr_channel_t ch,
void *  uctx,
fr_channel_recv_callback_t  recv_reply 
)

Definition at line 930 of file channel.c.

+ Here is the caller graph for this function:

◆ fr_channel_set_recv_request()

int fr_channel_set_recv_request ( fr_channel_t ch,
void *  uctx,
fr_channel_recv_callback_t  recv_request 
)

Definition at line 938 of file channel.c.

+ Here is the caller graph for this function:

◆ fr_channel_signal_open()

int fr_channel_signal_open ( fr_channel_t ch)

Send a channel to a responder.

Parameters
[in]chThe channel.
Returns
  • <0 on error
  • 0 on success

Definition at line 952 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_signal_responder_close()

int fr_channel_signal_responder_close ( fr_channel_t ch)

Signal a responder that the channel is closing.

Parameters
[in]chThe channel.
Returns
  • <0 on error
  • 0 on success

Definition at line 824 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_channel_stats_log()

void fr_channel_stats_log ( fr_channel_t const *  ch,
fr_log_t const *  log,
char const *  file,
int  line 
)

Definition at line 963 of file channel.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ channel_packet_priority

fr_table_num_sorted_t const channel_packet_priority[]
Initial value:
= {
{ L("high"), PRIORITY_HIGH },
{ L("low"), PRIORITY_LOW },
{ L("normal"), PRIORITY_NORMAL },
{ L("now"), PRIORITY_NOW }
}
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define PRIORITY_NORMAL
Definition: channel.h:151
#define PRIORITY_NOW
Definition: channel.h:149
#define PRIORITY_HIGH
Definition: channel.h:150
#define PRIORITY_LOW
Definition: channel.h:152

Definition at line 164 of file channel.c.

◆ channel_packet_priority_len

size_t channel_packet_priority_len = NUM_ELEMENTS(channel_packet_priority)

Definition at line 170 of file channel.c.

◆ channel_signals

fr_table_num_sorted_t const channel_signals[]
Initial value:
= {
{ L("error"), FR_CHANNEL_ERROR },
{ L("data-to-responder"), FR_CHANNEL_SIGNAL_DATA_TO_RESPONDER },
{ L("data-to-requestor"), FR_CHANNEL_DATA_READY_REQUESTOR },
{ L("open"), FR_CHANNEL_OPEN },
{ L("close"), FR_CHANNEL_CLOSE },
{ L("data-done-responder"), FR_CHANNEL_SIGNAL_DATA_DONE_RESPONDER },
{ L("responder-sleeping"), FR_CHANNEL_SIGNAL_RESPONDER_SLEEPING },
}
@ FR_CHANNEL_SIGNAL_DATA_DONE_RESPONDER
Definition: channel.c:93
@ FR_CHANNEL_SIGNAL_DATA_TO_RESPONDER
Definition: channel.c:84
@ FR_CHANNEL_SIGNAL_RESPONDER_SLEEPING
Definition: channel.c:94
@ FR_CHANNEL_CLOSE
Definition: channel.h:72
@ FR_CHANNEL_ERROR
Definition: channel.h:68
@ FR_CHANNEL_DATA_READY_REQUESTOR
Definition: channel.h:70
@ FR_CHANNEL_OPEN
Definition: channel.h:71

Definition at line 153 of file channel.c.

◆ channel_signals_len

size_t channel_signals_len = NUM_ELEMENTS(channel_signals)

Definition at line 162 of file channel.c.