summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-10-21 04:44:20 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-10-21 04:53:17 +0200
commitaa15b96d39dd0242c33b7a11c7c02ebdba50f150 (patch)
treeaa28611f444abae67869b1d33b7d3a063629615c
parenta45854b5d8dc699e68c5b538e299d5ef8fda59f3 (diff)
downloadffd-aa15b96d39dd0242c33b7a11c7c02ebdba50f150.tar
ffd-aa15b96d39dd0242c33b7a11c7c02ebdba50f150.zip
Add infrastructure for ack handling
-rw-r--r--ffd/CMakeLists.txt1
-rw-r--r--ffd/ack.c88
-rw-r--r--ffd/ffd.c14
-rw-r--r--ffd/ffd.h6
4 files changed, 107 insertions, 2 deletions
diff --git a/ffd/CMakeLists.txt b/ffd/CMakeLists.txt
index 830fef4..2cc8cd4 100644
--- a/ffd/CMakeLists.txt
+++ b/ffd/CMakeLists.txt
@@ -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
diff --git a/ffd/ack.c b/ffd/ack.c
new file mode 100644
index 0000000..0dbb13c
--- /dev/null
+++ b/ffd/ack.c
@@ -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);
+}
diff --git a/ffd/ffd.c b/ffd/ffd.c
index 9acd201..6b01cd3 100644
--- a/ffd/ffd.c
+++ b/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;
diff --git a/ffd/ffd.h b/ffd/ffd.h
index 42d679c..b78f7af 100644
--- a/ffd/ffd.h
+++ b/ffd/ffd.h
@@ -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);