Add infrastructure for ack handling
This commit is contained in:
parent
a45854b5d8
commit
aa15b96d39
4 changed files with 107 additions and 2 deletions
|
@ -1,6 +1,7 @@
|
|||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${FFD_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(ffd
|
||||
ack.c
|
||||
announce.c
|
||||
ffd.c
|
||||
neigh.c
|
||||
|
|
88
ffd/ack.c
Normal file
88
ffd/ack.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "ffd.h"
|
||||
#include "queue.h"
|
||||
|
||||
|
||||
static uint8_t acks[1 << 13] = {};
|
||||
static ffd_queue_t *ack_requests = NULL;
|
||||
static uint16_t nonce = 0;
|
||||
|
||||
|
||||
#define SET_ACK(n) do {acks[n >> 3] |= 1 << (n & 7);} while(0)
|
||||
#define UNSET_ACK(n) do {acks[n >> 3] &= ~(1 << (n & 7));} while(0)
|
||||
#define GET_ACK(n) ((acks[n >> 3] & (1 << (n & 7))) != 0)
|
||||
|
||||
|
||||
typedef struct _ack_arg_t {
|
||||
void (*cb)(uint16_t nonce, void *arg);
|
||||
void *arg;
|
||||
|
||||
uint16_t nonce;
|
||||
unsigned interval;
|
||||
unsigned retries;
|
||||
} ack_arg_t;
|
||||
|
||||
|
||||
void ffd_ack_handle(uint16_t n) {
|
||||
SET_ACK(n);
|
||||
}
|
||||
|
||||
static void ack_resend(const struct timespec *timeout, void *argp) {
|
||||
ack_arg_t *arg = argp;
|
||||
|
||||
if (GET_ACK(arg->nonce) || !(--arg->retries)) {
|
||||
free(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
arg->cb(arg->nonce, arg->arg);
|
||||
|
||||
ffd_queue_put_delayed(&ack_requests, ack_resend, timeout, arg->interval, arg);
|
||||
}
|
||||
|
||||
void ffd_ack_request(void (*cb)(uint16_t nonce, void *arg), unsigned interval, unsigned retries, void *arg) {
|
||||
UNSET_ACK(nonce);
|
||||
cb(nonce, arg);
|
||||
|
||||
ack_arg_t *ack_arg = malloc(sizeof(ack_arg_t));
|
||||
ack_arg->cb = cb;
|
||||
ack_arg->arg = arg;
|
||||
ack_arg->nonce = nonce++;
|
||||
ack_arg->interval = interval;
|
||||
ack_arg->retries = retries;
|
||||
|
||||
ffd_queue_put_delayed(&ack_requests, ack_resend, &now, interval, ack_arg);
|
||||
}
|
||||
|
||||
int ffd_ack_timeout(void) {
|
||||
return ffd_queue_timeout(&ack_requests);
|
||||
}
|
||||
|
||||
void ffd_ack_run(void) {
|
||||
ffd_queue_run(&ack_requests);
|
||||
}
|
14
ffd/ffd.c
14
ffd/ffd.c
|
@ -203,6 +203,15 @@ static void handle_tlv_ack_req(const ffd_tlv_ack_req_t *tlv_req, size_t len, han
|
|||
ffd_send_ack(neigh, ntohs(tlv_req->nonce));
|
||||
}
|
||||
|
||||
static void handle_tlv_ack(const ffd_tlv_ack_t *tlv_ack, size_t len, handle_tlv_arg_t *arg) {
|
||||
if (len < sizeof(ffd_tlv_ack_t)) {
|
||||
fprintf(stderr, "warn: received short acknowledement TLV.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ffd_ack_handle(ntohs(tlv_ack->nonce));
|
||||
}
|
||||
|
||||
static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, handle_tlv_arg_t *arg) {
|
||||
if (len < sizeof(ffd_tlv_hello_t)) {
|
||||
fprintf(stderr, "warn: received short hello TLV.\n");
|
||||
|
@ -425,7 +434,7 @@ static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *
|
|||
return;
|
||||
|
||||
case TLV_ACK:
|
||||
/* we don't send ack reqs */
|
||||
handle_tlv_ack(data, len, arg);
|
||||
return;
|
||||
|
||||
case TLV_HELLO:
|
||||
|
@ -617,10 +626,11 @@ int main() {
|
|||
while (true) {
|
||||
ffd_queue_run(&tasks);
|
||||
ffd_update_run();
|
||||
ffd_ack_run();
|
||||
|
||||
struct pollfd fds[1];
|
||||
|
||||
int timeout = 10*timeout_min(ffd_queue_timeout(&tasks), ffd_update_timeout());
|
||||
int timeout = 10*timeout_min(timeout_min(ffd_queue_timeout(&tasks), ffd_update_timeout()), ffd_ack_timeout());
|
||||
if (timeout < 0)
|
||||
timeout = -1;
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
#define FFD_DELAY (FFD_HELLO_INTERVAL/2)
|
||||
#define FFD_URGENT_DELAY 20
|
||||
#define FFD_ACK_INTERVAL FFD_URGENT_DELAY
|
||||
|
||||
#define FFD_UPDATE_WITH_DATA 0x01
|
||||
|
||||
|
@ -207,6 +208,11 @@ ffd_nexthop_t* ffd_announce_nexthop_new(ffd_announce_t *announce, ffd_neigh_t *n
|
|||
bool ffd_announce_seqno_request(ffd_announce_t *announce, ffd_neigh_t *neigh, uint16_t seqno);
|
||||
void ffd_announce_free(ffd_announce_t *announce);
|
||||
|
||||
void ffd_ack_handle(uint16_t n);
|
||||
void ffd_ack_request(void (*cb)(uint16_t nonce, void *arg), unsigned interval, unsigned retries, void *arg);
|
||||
int ffd_ack_timeout(void);
|
||||
void ffd_ack_run(void);
|
||||
|
||||
void ffd_update_enqueue(const ffd_node_id_t *node, uint16_t type, uint16_t key, ffd_neigh_t *neigh, bool urgent);
|
||||
int ffd_update_timeout(void);
|
||||
void ffd_update_run(void);
|
||||
|
|
Reference in a new issue