|
static int8_t | _entry_cmp (void const *one, void const *two) |
|
fr_bio_t * | fr_bio_dedup_alloc (TALLOC_CTX *ctx, size_t max_saved, fr_bio_dedup_receive_t receive, fr_bio_dedup_release_t release, fr_bio_dedup_get_item_t get_item, fr_bio_dedup_config_t const *cfg, fr_bio_t *next) |
| Allocate a fr_bio_dedup_t. More...
|
|
static ssize_t | fr_bio_dedup_blocked (fr_bio_dedup_t *my, fr_bio_dedup_entry_t *item, ssize_t rcode) |
| The write is blocked. More...
|
|
static ssize_t | fr_bio_dedup_blocked_data (fr_bio_dedup_t *my, uint8_t const *buffer, size_t size, ssize_t rcode) |
| The write is blocked, but we don't have "item". More...
|
|
static int | fr_bio_dedup_buffer_save (fr_bio_dedup_t *my, uint8_t const *buffer, size_t size, ssize_t rcode) |
| Save partially written data to our local buffer. More...
|
|
static ssize_t | fr_bio_dedup_buffer_write (fr_bio_dedup_t *my) |
| Write data from our local buffer to the next bio. More...
|
|
static int | fr_bio_dedup_destructor (fr_bio_dedup_t *my) |
| Remove the dedup cache. More...
|
|
void | fr_bio_dedup_entry_cancel (fr_bio_t *bio, fr_bio_dedup_entry_t *item) |
| Cancel one item. More...
|
|
int | fr_bio_dedup_entry_extend (fr_bio_t *bio, fr_bio_dedup_entry_t *item, fr_time_t expires) |
| Extend the expiry time for an entry. More...
|
|
static ssize_t | fr_bio_dedup_flush_pending (fr_bio_dedup_t *my) |
| Flush any packets in the pending queue. More...
|
|
static ssize_t | fr_bio_dedup_read (fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size) |
|
static void | fr_bio_dedup_release (fr_bio_dedup_t *my, fr_bio_dedup_entry_t *item, fr_bio_dedup_release_reason_t reason) |
| Release an entry back to the free list. More...
|
|
static void | fr_bio_dedup_replied (fr_bio_dedup_t *my, fr_bio_dedup_entry_t *item) |
| Move an item from active to replied. More...
|
|
ssize_t | fr_bio_dedup_respond (fr_bio_t *bio, fr_bio_dedup_entry_t *item) |
| Resend a reply when we receive a duplicate request. More...
|
|
static void | fr_bio_dedup_timer (UNUSED fr_event_list_t *el, fr_time_t now, void *uctx) |
| Expire an entry when its timer fires. More...
|
|
static int | fr_bio_dedup_timer_reset (fr_bio_dedup_t *my) |
| Reset the timer after changing the rb tree. More...
|
|
static void | fr_bio_dedup_timer_reset_item (fr_bio_dedup_t *my, fr_bio_dedup_entry_t *item) |
|
static ssize_t | fr_bio_dedup_write (fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size) |
| Write raw data to the bio. More...
|
|
static ssize_t | fr_bio_dedup_write_data (fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size) |
| There's a partial block of data written. More...
|
|
static ssize_t | fr_bio_dedup_write_partial (fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size) |
| There's a partial packet written. More...
|
|
Binary IO abstractions for deduping packets.
- Id
- fbf88c1a785fa0f8894f5029d0e2871a8c49f745
The dedup BIO receives packets from the network, and allows for deduplication of replies. The actual deduplication tree / table has to be maintained by the calling application, as packet dedup is very protocol-specific. The purpose of the dedup BIO is to abstract all of the common support functions around this requirement.
When packets are read() from the next bio, the fr_bio_dedup_receive_t callback is run. It tells the BIO whether or not the packet should be received, and whether or not the packet should be returned to the caller. The receive callback is also passed a fr_bio_dedup_entry_t pointer, where the packet_ctx, packet, and size are already filled out. This entry is used to correlate requests and replies.
When packets are write() to the network, the fr_bio_dedup_get_item_t callback is called to get the previously cached fr_bio_dedup_entry_t pointer. This is because there is no generic way to get an additional context to this BIO via the write() routine. i.e. the packet_ctx for write() may include things like src/dst ip/port, and therefore can't always be an fr_bio_dedup_entry_t. The caller should associate the fr_bio_dedup_entry_t with the packet_ctx for the reply. The get_item() routine can then return the entry.
For simplicity, the next bio should be a memory one. That way the read() can read more than one packet if necessary. And the write() can cache a partial packet if it blocks.
The entry needs to be cached in order to maintain the internal tracking used by the dedup BIO.
On client retransmit, the fr_bio_dedup_receive_t callback is run, just as if it is a new packet. The dedup BIO does not know if the received data is a new packet until the fr_bio_dedup_receive_t callback says so. On duplicate client request, the fr_bio_dedup_receive_t callback can call fr_bio_dedup_respond() to send a duplicate reply. That call bypasses the normal dedup stack, and writes directly to the next bio.
The calling application can also call fr_bio_dedup_respond() as soon as it has a reply. i.e. skip the BIO write() call. That works, and is safe.
The dedup BIO tracks a number of lists / trees internally. Packets which are received but which have no reply are in an "active" list. Packets which have a reply are in an "expired" RB tree, where a timer is set to expire packets. If a write() call results in a partial write, that packet is put into a "partially
written" state. If multiple calls to write() are done when writing is blocked, the replies are put into a "pending" state.
The calling application can always call fr_bio_dedup_cancel() to cancel or expire a packet. This call is safe, and can be made at any time, no matter what state the packet is in.
- Copyright
- 2024 Network RADIUS SAS (legal.nosp@m.@net.nosp@m.workr.nosp@m.adiu.nosp@m.s.com)
Definition in file dedup.c.