From bb7392551ed8578171941b81cf3ed2cfc4ad2b1b Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 5 Oct 2012 04:26:02 +0200 Subject: Lots of update handling --- ffd/ffd.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 4 deletions(-) (limited to 'ffd/ffd.c') diff --git a/ffd/ffd.c b/ffd/ffd.c index 3512906..5f17446 100644 --- a/ffd/ffd.c +++ b/ffd/ffd.c @@ -98,9 +98,8 @@ static bool init_self(void) { announce->node = self; announce->type = 1; announce->key = 1337; - announce->interval = 6000; - announce->nexthop_list = calloc(1, sizeof(ffd_nexthop_t)); + announce->nexthop_list = announce->selected = calloc(1, sizeof(ffd_nexthop_t)); return true; } @@ -273,13 +272,107 @@ 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 void handle_tlv_update(const ffd_tlv_node_id_t *tlv_node_id, size_t len, handle_tlv_arg_t *arg) { +static ffd_announce_t* get_announce(const ffd_node_id_t *node, uint16_t type, uint16_t key) { + ffd_announce_t *announce; + for (announce = announce_list; announce; announce = announce->next) { + if (ffd_are_node_ids_equal(&announce->node, node) + && announce->type == type + && announce->key == key) + return announce; + } + + /* not found */ + announce = ffd_announce_new(); + announce->node = *node; + announce->type = type; + announce->key = key; + + return announce; +} + +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; + + 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"); return; } + if (ffd_is_node_id_unspec(&arg->node_id)) { + fprintf(stderr, "warn: received update TLV without node id TLV.\n"); + return; + } + + if (ffd_are_node_ids_equal(&arg->node_id, &self)) { + fprintf(stderr, "debug: update source is myself.\n"); + return; + } + fprintf(stderr, "debug: update received from %04x%04x.\n", ntohl(*(uint32_t*)arg->node_id.id), ntohl(*(uint32_t*)(arg->node_id.id+4))); + + ffd_announce_t *announce = get_announce(&arg->node_id, ntohs(tlv_update->type), ntohs(tlv_update->key)); + ffd_metric_seqno_t ms = { ntohs(tlv_update->metric), ntohs(tlv_update->seqno) }; + bool feasable = ffd_is_feasable(announce, ms); + + ffd_neigh_t *neigh = get_tlv_neigh(arg); + ffd_nexthop_t *nexthop = find_nexthop(announce, neigh); + + if (!nexthop) { + if (!feasable || tlv_update->metric == 0xffff /* no need to ntohs */) + return; + + nexthop = new_nexthop(announce, neigh); + } + else { + if (!feasable && nexthop == announce->selected) + return; + } + + nexthop->metric_seqno.metric = ntohs(tlv_update->metric); + nexthop->metric_seqno.seqno = ntohs(tlv_update->seqno); + nexthop->interval = ntohs(tlv_update->interval); + + fprintf(stderr, "debug: the update was accepted.\n"); + + if (nexthop->metric_seqno.metric == 0xffff) + return; + + /* only update the timestamp for finite metrics */ + nexthop->last_update = now; + + if ((tlv_update->flags & FFD_UPDATE_WITH_DATA) && !announce->data) { + if (len > sizeof(ffd_tlv_update_t)) { + announce->len = len - sizeof(ffd_tlv_update_t); + announce->data = malloc(announce->len); + memcpy(announce->data, tlv_update->data, announce->len); + } + else { + announce->len = 0xff; + + /* request data */ + ffd_send_announce_request(arg->iface, neigh, announce->node, announce->type, announce->key, true); + } + } + + ffd_announce_update_nexthop(announce); } static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_t len, handle_tlv_arg_t *arg) { @@ -294,7 +387,7 @@ static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_ announce = NULL; } - ffd_send_update(arg->iface, get_tlv_neigh(arg), announce); + ffd_send_update(arg->iface, get_tlv_neigh(arg), announce, tlv_req->flags & FFD_UPDATE_WITH_DATA); } static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) { -- cgit v1.2.3