diff --git a/ffd/CMakeLists.txt b/ffd/CMakeLists.txt index 2cc8cd4..1571580 100644 --- a/ffd/CMakeLists.txt +++ b/ffd/CMakeLists.txt @@ -1,15 +1,12 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${FFD_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) add_executable(ffd - ack.c announce.c ffd.c neigh.c netif.c - queue.c send.c tlv.c - update.c util.c ) target_link_libraries(ffd rt) diff --git a/ffd/ack.c b/ffd/ack.c deleted file mode 100644 index cd21d0f..0000000 --- a/ffd/ack.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (c) 2012, Matthias Schiffer - 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 (*free)(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)) { - arg->free(arg->nonce, arg->arg); - 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), void (*free_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->free = free_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/announce.c b/ffd/announce.c index f68bb48..26ced28 100644 --- a/ffd/announce.c +++ b/ffd/announce.c @@ -26,7 +26,6 @@ #include "ffd.h" #include "neigh.h" -#include "send.h" #include @@ -111,26 +110,6 @@ ffd_metric_seqno_t get_metric(const ffd_announce_t *announce) { return (ffd_metric_seqno_t){0xffff, 0}; } -static inline void seqno_update(ffd_announce_t *announce) { - ffd_seqno_req_t **cur, **next; - for (cur = &announce->seqno_req_list; *cur; cur = next) { - ffd_seqno_req_t *req = *cur; - next = &req->next; - - int16_t diff = announce->selected->metric_seqno.seqno - req->seqno; - - if (diff >= 0) { - *cur = *next; - next = cur; - - fprintf(stderr, "debug: update matches seqno request, forwarding\n"); - ffd_update_enqueue(&announce->node, announce->type, announce->key, req->neigh, true); - ffd_neigh_unref(req->neigh); - free(req); - } - } -} - void ffd_announce_update(ffd_announce_t *announce) { maintain_nexthops(announce); @@ -146,11 +125,8 @@ void ffd_announce_update(ffd_announce_t *announce) { if (((announce->last_metric == 0xffff) != (announce->metric.metric == 0xffff)) || diff <= -1024 || diff >= 384) { fprintf(stderr, "info: announce metric has changed significantly, sending updates\n"); - ffd_update_enqueue(&announce->node, announce->type, announce->key, NULL, announce->metric.metric == 0xffff); + ffd_send_update(NULL, NULL, announce, false); } - - if (announce->selected) - seqno_update(announce); } void ffd_announce_update_nexthop(ffd_announce_t *announce, ffd_nexthop_t *nexthop, ffd_metric_seqno_t ms, uint16_t interval) { @@ -199,84 +175,3 @@ ffd_announce_t* ffd_announce_get(const ffd_node_id_t *node, uint16_t type, uint1 return announce; } - -ffd_nexthop_t* ffd_announce_nexthop_find(const ffd_announce_t *announce, ffd_neigh_t *neigh) { - ffd_nexthop_t *nexthop; - for (nexthop = announce->nexthop_list; nexthop; nexthop = nexthop->next) { - if (nexthop->neigh == neigh) - return nexthop; - } - - return NULL; -} - -ffd_nexthop_t* ffd_announce_nexthop_new(ffd_announce_t *announce, ffd_neigh_t *neigh) { - ffd_nexthop_t *nexthop = calloc(1, sizeof(ffd_nexthop_t)); - nexthop->neigh = neigh; - - nexthop->next = announce->nexthop_list; - announce->nexthop_list = nexthop; - - ffd_neigh_ref(neigh); - - return nexthop; -} - -static inline bool find_seqno_request(ffd_seqno_req_t **reqp, ffd_announce_t *announce, ffd_neigh_t *neigh, uint16_t seqno) { - ffd_seqno_req_t *req; - bool ret = true; - - *reqp = NULL; - - for (req = announce->seqno_req_list; req; req = req->next) { - if (req->neigh == neigh) - *reqp = req; - - int16_t diff = req->seqno - seqno; - if (timespec_diff(&now, &req->last_req) < FFD_SEQNO_REQUEST_TIMEOUT && diff >= 0) - ret = false; - } - - return ret; -} - -bool ffd_announce_seqno_request(ffd_announce_t *announce, ffd_neigh_t *neigh, uint16_t seqno) { - ffd_seqno_req_t *req; - bool ret = find_seqno_request(&req, announce, neigh, seqno); - - if (!req) { - req = calloc(1, sizeof(ffd_seqno_req_t)); - req->neigh = neigh; - req->seqno = seqno; - req->last_req = now; - - ffd_neigh_ref(neigh); - - req->next = announce->seqno_req_list; - announce->seqno_req_list = req; - } - - int16_t diff = seqno - req->seqno; - if (diff > 0) { - req->seqno = seqno; - req->last_req = now; - } - - if (ret) { - req->last_req = now; - return true; - } - - return false; -} - -void ffd_announce_free(ffd_announce_t *announce) { - ffd_seqno_req_t *req, *req_next; - for (req = announce->seqno_req_list; req; req = req_next) { - req_next = req->next; - ffd_neigh_unref(req->neigh); - free(req); - } - - free(announce); -} diff --git a/ffd/ffd.c b/ffd/ffd.c index 0504085..5e967f3 100644 --- a/ffd/ffd.c +++ b/ffd/ffd.c @@ -28,8 +28,6 @@ #include "neigh.h" #include "netif.h" #include "packet.h" -#include "queue.h" -#include "send.h" #include "tlv.h" #include "tlv_types.h" @@ -53,10 +51,10 @@ static char *mesh = "bat0"; int sockfd; struct timespec now; -static ffd_queue_t *tasks = NULL; - ffd_node_id_t self; + ffd_iface_t *iface_list = NULL; + ffd_announce_t *announce_list = NULL; @@ -203,15 +201,6 @@ 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"); @@ -295,6 +284,28 @@ static void handle_tlv_node_id(const ffd_tlv_node_id_t *tlv_node_id, size_t len, arg->node_id = tlv_node_id->id; } +static ffd_nexthop_t* find_nexthop(const ffd_announce_t *announce, ffd_neigh_t *neigh) { + ffd_nexthop_t *nexthop; + for (nexthop = announce->nexthop_list; nexthop; nexthop = nexthop->next) { + if (nexthop->neigh == neigh) + return nexthop; + } + + return NULL; +} + +static ffd_nexthop_t* new_nexthop(ffd_announce_t *announce, ffd_neigh_t *neigh) { + ffd_nexthop_t *nexthop = calloc(1, sizeof(ffd_nexthop_t)); + nexthop->neigh = neigh; + + nexthop->next = announce->nexthop_list; + announce->nexthop_list = nexthop; + + ffd_neigh_ref(neigh); + + return nexthop; +} + static void handle_tlv_update(const ffd_tlv_update_t *tlv_update, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(ffd_tlv_update_t)) { fprintf(stderr, "warn: received short update TLV.\n"); @@ -318,11 +329,11 @@ static void handle_tlv_update(const ffd_tlv_update_t *tlv_update, size_t len, ha bool feasible = ffd_is_feasible(announce, ms); ffd_neigh_t *neigh = get_tlv_neigh(arg); - ffd_nexthop_t *nexthop = ffd_announce_nexthop_find(announce, neigh); + ffd_nexthop_t *nexthop = find_nexthop(announce, neigh); if (!nexthop) { if (feasible && tlv_update->metric != 0xffff /* no need to ntohs */) - nexthop = ffd_announce_nexthop_new(announce, neigh); + nexthop = new_nexthop(announce, neigh); } else { if (!feasible && nexthop == announce->selected) { @@ -386,6 +397,8 @@ static void handle_tlv_seqno_req(const ffd_tlv_seqno_req_t *tlv_req, size_t len, return; } + fprintf(stderr, "debug: received seqno request\n"); + ffd_announce_t *announce = ffd_announce_find(&tlv_req->node, ntohs(tlv_req->type), ntohs(tlv_req->key)); if (!announce) { @@ -403,28 +416,21 @@ static void handle_tlv_seqno_req(const ffd_tlv_seqno_req_t *tlv_req, size_t len, if (announce->selected->neigh == neigh) return; - uint16_t seqno = ntohs(tlv_req->seqno); - - if ((int16_t)(seqno-announce->selected->metric_seqno.seqno) <= 0) { + if ((int16_t)(ntohs(tlv_req->seqno)-announce->selected->metric_seqno.seqno) <= 0) { fprintf(stderr, "debug: received seqno request, seqno already ok\n"); - ffd_update_enqueue(&announce->node, announce->type, announce->key, neigh, true); + ffd_send_update(NULL, neigh, announce, false); return; } if (!announce->selected->neigh) { - fprintf(stderr, "debug: received seqno request, incrementing seqno\n"); + fprintf(stderr, "debug: incrementing seqno\n"); announce->selected->metric_seqno.seqno++; - ffd_update_enqueue(&announce->node, announce->type, announce->key, neigh, true); + ffd_send_update(NULL, neigh, announce, false); return; } - if (ffd_announce_seqno_request(announce, neigh, seqno)) { - fprintf(stderr, "debug: received seqno request, forwarding\n"); - ffd_send_seqno_request(announce->selected->neigh, announce, seqno); - } - else { - fprintf(stderr, "debug: received seqno request, not forwarding again\n"); - } + fprintf(stderr, "debug: received seqno request, forwarding\n"); + ffd_send_seqno_request(announce->selected->neigh, announce, ntohs(tlv_req->seqno)); } static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) { @@ -434,7 +440,7 @@ static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void * return; case TLV_ACK: - handle_tlv_ack(data, len, arg); + /* we don't send ack reqs */ return; case TLV_HELLO: @@ -500,8 +506,6 @@ static void receive_packet(void) { } static void send_updates(void) { - fprintf(stderr, "debug: sending periodic updates.\n"); - ffd_iface_t *iface; for (iface = iface_list; iface; iface = iface->next) { ffd_send_update(iface, NULL, NULL, false); @@ -543,7 +547,7 @@ static void maintenance(void) { if (!announce->nexthop_list) { *cur = *next; next = cur; - ffd_announce_free(announce); + free(announce); continue; } @@ -570,46 +574,6 @@ static void maintenance(void) { } } - -typedef struct _periodic_task_info { - void (*handle)(void); - unsigned delay; - unsigned interval; -} periodic_task_info; - - -static const periodic_task_info periodic_tasks [] = { - {maintenance, 0, FFD_MAINTENANCE_INTERVAL}, - {ffd_send_hellos, FFD_HELLO_INTERVAL, FFD_HELLO_INTERVAL}, - {send_updates, 1, FFD_UPDATE_INTERVAL}, - {NULL} -}; - - -static void handle_periodic_task(const struct timespec *timeout, void *arg) { - const periodic_task_info *info = arg; - - info->handle(); - ffd_queue_put_delayed(&tasks, handle_periodic_task, timeout, info->interval, arg); -} - -static void register_periodic_tasks(void) { - const periodic_task_info *info; - for (info = periodic_tasks; info->handle; info++) - ffd_queue_put_delayed(&tasks, handle_periodic_task, &now, info->delay, (void*)info); -} - - -static inline int timeout_min(int a, int b) { - if (a < 0) - return b; - else if (b < 0) - return a; - else - return min(a, b); -} - - int main() { if (!check_config()) return 1; @@ -621,23 +585,44 @@ int main() { return 1; update_time(); - register_periodic_tasks(); + + struct timespec next_hello = now; + struct timespec next_update = now; + struct timespec next_maintenance = now; while (true) { - ffd_queue_run(&tasks); - ffd_update_run(); - ffd_ack_run(); + int maintenance_timeout = timespec_diff(&next_maintenance, &now); + if (maintenance_timeout <= 0) { + maintenance(); + + add_interval(&next_maintenance, FFD_MAINTENANCE_INTERVAL); + } + + int hello_timeout = timespec_diff(&next_hello, &now); + if (hello_timeout <= 0) { + ffd_send_hellos(); + + add_interval(&next_hello, FFD_HELLO_INTERVAL); + } + + int update_timeout = timespec_diff(&next_update, &now); + if (update_timeout <= 0) { + fprintf(stderr, "Sending periodic update.\n"); + send_updates(); + + add_interval(&next_update, FFD_UPDATE_INTERVAL); + } + + int timeout = min(min(hello_timeout, update_timeout), maintenance_timeout); + if (timeout <= 0) + continue; struct pollfd fds[1]; - int timeout = 10*timeout_min(timeout_min(ffd_queue_timeout(&tasks), ffd_update_timeout()), ffd_ack_timeout()); - if (timeout < 0) - timeout = -1; - fds[0].fd = sockfd; fds[0].events = POLLIN; - poll(fds, 1, timeout); + poll(fds, 1, 10*timeout); update_time(); diff --git a/ffd/ffd.h b/ffd/ffd.h index 2999be4..e7c48d7 100644 --- a/ffd/ffd.h +++ b/ffd/ffd.h @@ -47,13 +47,8 @@ #define FFD_UPDATE_REQUEST_TIMEOUT(interval) ((interval)*13/4) /* 3.25 intervals */ -#define FFD_SEQNO_REQUEST_TIMEOUT 50 - #define FFD_MAINTENANCE_INTERVAL FFD_HELLO_INTERVAL -#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 @@ -78,14 +73,6 @@ typedef struct _ffd_nexthop_t { bool requested_update; } ffd_nexthop_t; -typedef struct _ffd_seqno_req_t { - struct _ffd_seqno_req_t *next; - - struct timespec last_req; - struct _ffd_neigh_t *neigh; - uint16_t seqno; -} ffd_seqno_req_t; - typedef struct _ffd_announce_t { struct _ffd_announce_t *next; @@ -97,8 +84,6 @@ typedef struct _ffd_announce_t { uint16_t last_metric; ffd_metric_seqno_t feasibility_distance; - ffd_seqno_req_t *seqno_req_list; - ffd_nexthop_t *selected; ffd_nexthop_t *nexthop_list; @@ -148,6 +133,7 @@ extern ffd_iface_t *iface_list; extern ffd_announce_t *announce_list; extern int sockfd; +extern struct timespec now; #define FFD_NODE_ID_UNSPEC ((ffd_node_id_t){}) @@ -203,18 +189,19 @@ void ffd_announce_update_nexthop(ffd_announce_t *announce, ffd_nexthop_t *nextho ffd_announce_t* ffd_announce_new(void); ffd_announce_t* ffd_announce_find(const ffd_node_id_t *node, uint16_t type, uint16_t key); ffd_announce_t* ffd_announce_get(const ffd_node_id_t *node, uint16_t type, uint16_t key); -ffd_nexthop_t* ffd_announce_nexthop_find(const ffd_announce_t *announce, ffd_neigh_t *neigh); -ffd_nexthop_t* ffd_announce_nexthop_new(ffd_announce_t *announce, ffd_neigh_t *neigh); -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), void (*free_cb)(uint16_t nonce, void *arg), unsigned interval, unsigned retries, void *arg); -int ffd_ack_timeout(void); -void ffd_ack_run(void); +void ffd_send_ack(ffd_neigh_t *neigh, uint16_t nonce); +void ffd_send_hellos(void); +void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *announce, bool with_data); +void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key); +void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data); +void ffd_send_seqno_request(ffd_neigh_t *neigh, ffd_announce_t *announce, uint16_t seqno); -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); +static inline void ffd_send_seqno_request_for(ffd_neigh_t *neigh, ffd_announce_t *announce) { + if (FFD_IS_INFINITY(announce->feasibility_distance)) + return; + + ffd_send_seqno_request(neigh, announce, announce->feasibility_distance.seqno+1); +} #endif /* _FFD_FFD_H_ */ diff --git a/ffd/neigh.c b/ffd/neigh.c index e8e7d0f..1b0d41d 100644 --- a/ffd/neigh.c +++ b/ffd/neigh.c @@ -25,7 +25,6 @@ #include "neigh.h" -#include "send.h" ffd_neigh_t* ffd_neigh_get(ffd_iface_t *iface, const eth_addr_t *addr) { @@ -56,11 +55,6 @@ void ffd_neigh_unref_list(ffd_neigh_t *neigh) { } } -void ffd_neigh_unref(ffd_neigh_t *neigh) { - if (!(--neigh->ref) && !neigh->iface) - free(neigh); -} - uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh) { if (!neigh->hello_log || !neigh->hello_interval || !neigh->iface) return 0xffff; diff --git a/ffd/neigh.h b/ffd/neigh.h index 3e84a8e..aa0d1f9 100644 --- a/ffd/neigh.h +++ b/ffd/neigh.h @@ -44,6 +44,10 @@ static inline void ffd_neigh_ref(ffd_neigh_t *neigh) { neigh->ref++; } +static inline void ffd_neigh_unref(ffd_neigh_t *neigh) { + if (!(--neigh->ref) && !neigh->iface) + free(neigh); +} ffd_neigh_t* ffd_neigh_get(ffd_iface_t *iface, const eth_addr_t *addr); void ffd_neigh_unref(ffd_neigh_t *neigh); diff --git a/ffd/queue.c b/ffd/queue.c deleted file mode 100644 index 23f96bc..0000000 --- a/ffd/queue.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (c) 2012, Matthias Schiffer - 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 "queue.h" - - -void ffd_queue_put(ffd_queue_t **queue, ffd_queue_cb cb, const struct timespec *timeout, void *arg) { - while (*queue && timespec_after(timeout, &(*queue)->timeout)) - queue = &(*queue)->next; - - ffd_queue_t *entry = malloc(sizeof(ffd_queue_t)); - - entry->cb = cb; - entry->timeout = *timeout; - entry->arg = arg; - - entry->next = *queue; - *queue = entry; -} diff --git a/ffd/queue.h b/ffd/queue.h deleted file mode 100644 index f9b8008..0000000 --- a/ffd/queue.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - Copyright (c) 2012, Matthias Schiffer - 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. -*/ - - -#ifndef _FFD_QUEUE_H_ -#define _FFD_QUEUE_H_ - -#include "util.h" - - -typedef void (*ffd_queue_cb)(const struct timespec *timeout, void *arg); - -struct _ffd_queue_t { - ffd_queue_t *next; - ffd_queue_cb cb; - struct timespec timeout; - void *arg; -}; - - -void ffd_queue_put(ffd_queue_t **queue, ffd_queue_cb cb, const struct timespec *timeout, void *arg); - - -static inline void ffd_queue_put_delayed(ffd_queue_t **queue, ffd_queue_cb cb, const struct timespec *timeout, int delay, void *arg) { - struct timespec timeout_delayed = *timeout; - add_interval(&timeout_delayed, delay); - ffd_queue_put(queue, cb, &timeout_delayed, arg); -} - -static inline void ffd_queue_drop(ffd_queue_t **queue) { - ffd_queue_t *entry = *queue; - *queue = entry->next; - free(entry); -} - -static inline void ffd_queue_run(ffd_queue_t **queue) { - while (*queue && timespec_after(&now, &(*queue)->timeout)) { - ffd_queue_t *entry = *queue; - *queue = (*queue)->next; - - entry->cb(&entry->timeout, entry->arg); - free(entry); - } -} - -static inline int ffd_queue_timeout(ffd_queue_t *const *queue) { - if (!*queue) - return -1; - - return max(timespec_diff(&(*queue)->timeout, &now), 0); -} - -#endif /* _FFD_QUEUE_H_ */ diff --git a/ffd/send.c b/ffd/send.c index 2cd57bf..ebda0de 100644 --- a/ffd/send.c +++ b/ffd/send.c @@ -27,7 +27,6 @@ #include "ffd.h" #include "neigh.h" #include "packet.h" -#include "send.h" #include "tlv.h" #include "tlv_types.h" @@ -41,27 +40,6 @@ #include - -typedef struct _announce_info_t { - ffd_node_id_t node; - uint16_t type; - uint16_t key; -} announce_info_t; - -struct _ffd_update_t { - ffd_iface_t *iface; - ffd_neigh_t *neigh; - - ffd_packet_t *packet; - size_t max_len; - - ffd_node_id_t node; - - unsigned n_updates; - announce_info_t announces[]; -}; - - static bool send_eth(const eth_addr_t *addr, unsigned ifindex, const void *buf, size_t len) { static const uint8_t zeros[46] = {0}; @@ -188,18 +166,6 @@ void ffd_send_hellos(void) { } } -static bool add_ack_request(ffd_packet_t *packet, uint16_t nonce) { - ffd_tlv_ack_req_t *tlv = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_ACK_REQ, sizeof(ffd_tlv_ack_req_t)); - if (!tlv) - return false; - - tlv->reserved = 0; - tlv->nonce = htons(nonce); - tlv->interval = htons(FFD_ACK_INTERVAL); - - return true; -} - static bool add_node_id(ffd_packet_t *packet, size_t max_len, ffd_node_id_t node_id) { ffd_tlv_node_id_t *tlv = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_NODE_ID, sizeof(ffd_tlv_node_id_t)); if (!tlv) @@ -257,34 +223,6 @@ static bool add_update(ffd_packet_t *packet, size_t max_len, ffd_node_id_t *node return true; } -static bool add_retract(ffd_packet_t *packet, size_t max_len, ffd_node_id_t *node_id, ffd_node_id_t node, uint16_t type, uint16_t key) { - uint16_t len = packet->len; - - if (!node_id || !ffd_are_node_ids_equal(node_id, &node)) { - if (!add_node_id(packet, max_len, node)) - return false; - - if (node_id) - *node_id = node; - } - - ffd_tlv_update_t *update = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_UPDATE, sizeof(ffd_tlv_update_t)); - if (!update) { - packet->len = len; - return false; - } - - update->flags = 0; - update->reserved = 0; - update->interval = htons(FFD_UPDATE_INTERVAL); - update->seqno = 0; - update->metric = 0xffff; /* no need to htons */ - update->type = htons(type); - update->key = htons(key); - - return true; -} - void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *announce, bool with_data) { ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX); @@ -326,83 +264,21 @@ void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uin if (!add_node_id(packet, FFD_PACKET_MAX, node)) return; - ffd_tlv_update_t *update = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_UPDATE, sizeof(ffd_tlv_update_t)); - if (!update) + ffd_tlv_update_t *req = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_UPDATE, sizeof(ffd_tlv_update_t)); + if (!req) return; - update->flags = 0; - update->reserved = 0; - update->interval = htons(FFD_UPDATE_INTERVAL); - update->seqno = 0; - update->metric = 0xffff; /* no need to htons */ - update->type = htons(type); - update->key = htons(key); + req->flags = 0; + req->reserved = 0; + req->interval = htons(FFD_UPDATE_INTERVAL); + req->seqno = 0; + req->metric = 0xffff; /* no need to htons */ + req->type = htons(type); + req->key = htons(key); send_neigh(neigh, packet); } -ffd_update_t* ffd_send_update_new(ffd_iface_t *iface, ffd_neigh_t *neigh, const uint16_t *nonce) { - unsigned max_updates = (FFD_PACKET_MAX+sizeof(ffd_tlv_update_t)+1)/(sizeof(ffd_tlv_update_t)+2); - ffd_update_t *update = calloc(1, sizeof(ffd_update_t) + max_updates*sizeof(announce_info_t)); - update->iface = iface; - update->neigh = neigh; - - update->max_len = FFD_PACKET_MAX; - update->packet = malloc(sizeof(ffd_packet_t)+FFD_PACKET_MAX); - update->packet->version_magic = htons(FFD_VERSION_MAGIC); - update->packet->len = 0; - - if (nonce) - add_ack_request(update->packet, *nonce); - - return update; -} - -static inline bool is_update_duplicate(ffd_update_t *update, ffd_node_id_t node, uint16_t type, uint16_t key) { - unsigned i; - for (i = 0; i < update->n_updates; i++) { - if (ffd_are_node_ids_equal(&update->announces[i].node, &node) - && update->announces[i].type == type && update->announces[i].key == key) - return true; - } - - return false; -} - -bool ffd_send_update_add(ffd_update_t *update, ffd_announce_t *announce) { - if (is_update_duplicate(update, announce->node, announce->type, announce->key)) - return false; - - if (!add_update(update->packet, update->max_len, &update->node, announce, false, update->neigh)) - return false; - - update->announces[update->n_updates++] = (announce_info_t){announce->node, announce->type, announce->key}; - - return true; -} - -bool ffd_send_update_retract(ffd_update_t *update, ffd_node_id_t node, uint16_t type, uint16_t key) { - if (is_update_duplicate(update, node, type, key)) - return false; - - if (!add_retract(update->packet, update->max_len, &update->node, node, type, key)) - return false; - - update->announces[update->n_updates++] = (announce_info_t){node, type, key}; - - return true; -} - -void ffd_send_update_finish(ffd_update_t *update) { - fprintf(stderr, "debug: sending %u aggregated update(s).\n", update->n_updates); - - if (update->packet->len) - send_any(update->iface, update->neigh, update->packet); - - free(update->packet); - free(update); -} - void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data) { ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX); diff --git a/ffd/send.h b/ffd/send.h deleted file mode 100644 index 50a61e2..0000000 --- a/ffd/send.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (c) 2012, Matthias Schiffer - 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. -*/ - - -#ifndef _FFD_SEND_H_ -#define _FFD_SEND_H_ - -#include "ffd.h" - - -typedef struct _ffd_update_t ffd_update_t; - - -void ffd_send_ack(ffd_neigh_t *neigh, uint16_t nonce); -void ffd_send_hellos(void); -void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *announce, bool with_data); -void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key); -void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data); -void ffd_send_seqno_request(ffd_neigh_t *neigh, ffd_announce_t *announce, uint16_t seqno); - -ffd_update_t* ffd_send_update_new(ffd_iface_t *iface, ffd_neigh_t *neigh, const uint16_t *nonce); -bool ffd_send_update_add(ffd_update_t *update, ffd_announce_t *announce); -bool ffd_send_update_retract(ffd_update_t *update, ffd_node_id_t node, uint16_t type, uint16_t key); -void ffd_send_update_finish(ffd_update_t *update); - - -static inline void ffd_send_seqno_request_for(ffd_neigh_t *neigh, ffd_announce_t *announce) { - if (FFD_IS_INFINITY(announce->feasibility_distance)) - return; - - ffd_send_seqno_request(neigh, announce, announce->feasibility_distance.seqno+1); -} - -#endif /* _FFD_SEND_H_ */ diff --git a/ffd/types.h b/ffd/types.h index b20d691..f0c6c39 100644 --- a/ffd/types.h +++ b/ffd/types.h @@ -41,6 +41,6 @@ typedef struct __attribute__((packed)) _eth_addr_t { typedef struct _ffd_packet_t ffd_packet_t; -typedef struct _ffd_queue_t ffd_queue_t; + #endif /* _FFD_TYPES_H_ */ diff --git a/ffd/update.c b/ffd/update.c deleted file mode 100644 index 7ae760a..0000000 --- a/ffd/update.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - Copyright (c) 2012, Matthias Schiffer - 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 "neigh.h" -#include "queue.h" -#include "send.h" - -#include - - -static ffd_queue_t *pending_updates = NULL; - - -typedef struct _update_arg_t { - ffd_node_id_t node; - uint16_t type; - uint16_t key; - - ffd_neigh_t *neigh; - unsigned ref; -} update_arg_t; - - -static inline update_arg_t* update_new(const ffd_node_id_t *node, uint16_t type, uint16_t key, ffd_neigh_t *neigh) { - update_arg_t *arg = malloc(sizeof(update_arg_t)); - - arg->node = *node; - arg->type = type; - arg->key = key; - - if (neigh) - ffd_neigh_ref(neigh); - arg->neigh = neigh; - - arg->ref = 0; - - return arg; -} - -static inline update_arg_t* update_ref(update_arg_t *arg) { - arg->ref++; - return arg; -} - -static inline void update_unref(update_arg_t *arg) { - if (!--arg->ref) { - if (arg->neigh) - ffd_neigh_unref(arg->neigh); - - free(arg); - } -} - -static void update_request_ack(uint16_t nonce, void *argp) { - update_arg_t *arg = argp; - - fprintf(stderr, "debug: sending acked update with nonce %u.\n", nonce); - - ffd_update_t *update = ffd_send_update_new(NULL, arg->neigh, &nonce); - - ffd_announce_t *announce = ffd_announce_find(&arg->node, arg->type, arg->key); - - if (announce) - ffd_send_update_add(update, announce); - else - ffd_send_update_retract(update, arg->node, arg->type, arg->key); - - ffd_send_update_finish(update); -} - -static void update_request_ack_free(uint16_t nonce, void *arg) { - update_unref(arg); -} - -void ffd_update_enqueue(const ffd_node_id_t *node, uint16_t type, uint16_t key, ffd_neigh_t *neigh, bool urgent) { - if (neigh) - ffd_neigh_ref(neigh); - - update_arg_t *arg = update_new(node, type, key, neigh); - - if (urgent) { - if (neigh) { - ffd_ack_request(update_request_ack, update_request_ack_free, FFD_ACK_INTERVAL, 10, update_ref(arg)); - } - else { - int i; - for (i = 1; i <= 5; i++) - ffd_queue_put_delayed(&pending_updates, NULL, &now, i*FFD_URGENT_DELAY, update_ref(arg)); - } - } - else { - ffd_queue_put_delayed(&pending_updates, NULL, &now, FFD_DELAY, update_ref(arg)); - } -} - -int ffd_update_timeout(void) { - return ffd_queue_timeout(&pending_updates); -} - -void ffd_update_run(void) { - while (!ffd_update_timeout()) { - ffd_neigh_t *neigh = ((update_arg_t*)pending_updates->arg)->neigh; - - ffd_update_t *update = ffd_send_update_new(NULL, neigh, NULL); - - fprintf(stderr, "debug: sending scheduled updates.\n"); - - ffd_queue_t **entry; - for (entry = &pending_updates; *entry;) { - update_arg_t *arg = (*entry)->arg; - - if (arg->neigh != neigh) { - entry = &(*entry)->next; - continue; - } - - ffd_announce_t *announce = ffd_announce_find(&arg->node, arg->type, arg->key); - bool ret; - - if (announce) - ret = ffd_send_update_add(update, announce); - else - ret = ffd_send_update_retract(update, arg->node, arg->type, arg->key); - - if (!ret) - break; - - update_unref(arg); - ffd_queue_drop(entry); - } - - ffd_send_update_finish(update); - } -} diff --git a/ffd/util.h b/ffd/util.h index 0660b94..9d481cb 100644 --- a/ffd/util.h +++ b/ffd/util.h @@ -34,9 +34,6 @@ #include -extern struct timespec now; - - bool file_readv(const char *file, const char *format, va_list ap); void random_bytes(void *buffer, size_t len); @@ -56,11 +53,6 @@ static inline bool are_eth_addrs_equal(const eth_addr_t *address1, const eth_add return (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3] && a[4]==b[4] && a[5]==b[5]); } -static inline bool timespec_after(const struct timespec *tp1, const struct timespec *tp2) { - return (tp1->tv_sec > tp2->tv_sec || - (tp1->tv_sec == tp2->tv_sec && tp1->tv_nsec > tp2->tv_nsec)); -} - /* returns (tp1 - tp2) in centiseconds */ static inline int timespec_diff(const struct timespec *tp1, const struct timespec *tp2) { return ((tp1->tv_sec - tp2->tv_sec))*100 + (tp1->tv_nsec - tp2->tv_nsec)/1e7;