From f29e37138a190c5cb43747433d687c944b7d2efe Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 1 Aug 2013 21:07:59 +0200 Subject: Simplify basic protocol, rename announces to routes, begin implementing route request handling --- src/CMakeLists.txt | 2 +- src/announce.c | 203 ----------------------------------------------------- src/babel.c | 38 +++++----- src/babel.h | 54 +++++++------- src/neigh.c | 4 +- src/neigh.h | 2 +- src/route.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/send.c | 135 +++++++++++++++++------------------ src/tlv.h | 2 +- src/tlv_types.c | 143 +++++++++++++++++++------------------ src/tlv_types.h | 13 ++-- src/types.h | 2 +- 12 files changed, 392 insertions(+), 405 deletions(-) delete mode 100644 src/announce.c create mode 100644 src/route.c (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da5e458..64cda12 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,9 +1,9 @@ include_directories(${GMRF_INCLUDE_DIR}) add_library(mmss_proto_babel MODULE - announce.c babel.c neigh.c + route.c send.c tlv.c tlv_types.c diff --git a/src/announce.c b/src/announce.c deleted file mode 100644 index 9deee18..0000000 --- a/src/announce.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - Copyright (c) 2013, 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 "babel.h" -#include "neigh.h" - -#include - - -gp_babel_announce_t* gp_babel_announce_new(gmrf_context_t *ctx) { - gp_babel_announce_t *a = calloc(1, sizeof(gp_babel_announce_t)); - - a->metric.metric = a->feasibility_distance.metric = a->last_metric = GP_BABEL_INFINITY; - - a->next = ctx->announces; - ctx->announces = a; - - return a; -} - -gp_babel_announce_t* gp_babel_announce_find(gmrf_context_t *ctx, const gp_babel_node_id_t *node, uint16_t type, uint16_t key) { - gp_babel_announce_t *announce; - for (announce = ctx->announces; announce; announce = announce->next) { - if (gp_babel_node_id_equal(&announce->node, node) - && announce->type == type - && announce->key == key) - return announce; - } - - return NULL; -} - -gp_babel_announce_t* gp_babel_announce_get(gmrf_context_t *ctx, const gp_babel_node_id_t *node, uint16_t type, uint16_t key) { - gp_babel_announce_t *announce = gp_babel_announce_find(ctx, node, type, key); - - if (!announce) { - announce = gp_babel_announce_new(ctx); - announce->node = *node; - announce->type = type; - announce->key = key; - } - - return announce; -} - -void gp_babel_announce_free(gmrf_context_t *ctx, gp_babel_announce_t *announce) { - free(announce); -} - -gp_babel_nexthop_t* gp_babel_announce_nexthop_find(const gp_babel_announce_t *announce, gp_babel_neigh_t *neigh) { - gp_babel_nexthop_t *nexthop; - for (nexthop = announce->nexthops; nexthop; nexthop = nexthop->next) { - if (nexthop->neigh == neigh) - return nexthop; - } - - return NULL; -} - -gp_babel_nexthop_t* gp_babel_announce_nexthop_new(gp_babel_announce_t *announce, gp_babel_neigh_t *neigh) { - gp_babel_nexthop_t *nexthop = calloc(1, sizeof(gp_babel_nexthop_t)); - nexthop->neigh = neigh; - - nexthop->next = announce->nexthops; - announce->nexthops = nexthop; - - gp_babel_neigh_ref(neigh); - - return nexthop; -} - -static void maintain_nexthops(gmrf_context_t *ctx, gp_babel_announce_t *announce) { - gp_babel_nexthop_t **cur, **next; - for (cur = &announce->nexthops; *cur; cur = next) { - gp_babel_nexthop_t *nexthop = *cur; - next = &nexthop->next; - - if (!nexthop->neigh) /* local */ - continue; - - if (!nexthop->neigh->iface) { - if (nexthop->metric_seqno.metric != GP_BABEL_INFINITY) { - nexthop->metric_seqno.metric = GP_BABEL_INFINITY; - nexthop->last_update = gmrf_now(ctx->gmrf); - nexthop->last_update += GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10; - } - - continue; - } - - if (gmrf_now(ctx->gmrf) > nexthop->last_update+GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10) { - if (nexthop->metric_seqno.metric == GP_BABEL_INFINITY) { - *cur = *next; - next = cur; - - if (announce->selected == nexthop) - announce->selected = NULL; - - gp_babel_neigh_unref(nexthop->neigh); - - free(nexthop); - } - else { - nexthop->metric_seqno.metric = GP_BABEL_INFINITY; - nexthop->last_update += GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10; - } - } - else if (gmrf_now(ctx->gmrf) > nexthop->last_update+GP_BABEL_UPDATE_REQUEST_TIMEOUT(nexthop->interval)*10 && announce->selected == nexthop) { - if (!nexthop->requested_update) { - gmrf_logf(ctx->gmrf, LOG_INFO, "announce about to expire, requesting update"); - gp_babel_send_announce_request(ctx, NULL, nexthop->neigh, &announce->node, announce->type, announce->key, false); - nexthop->requested_update = true; - } - } - } -} - -static gp_babel_nexthop_t* select_nexthop(gmrf_context_t *ctx, const gp_babel_announce_t *announce) { - uint16_t ret_metric = GP_BABEL_INFINITY; - gp_babel_nexthop_t *ret = NULL; - - gp_babel_nexthop_t *nexthop; - for (nexthop = announce->nexthops; nexthop; nexthop = nexthop->next) { - if (!nexthop->neigh) /* local */ - return nexthop; - - if (!gp_babel_is_feasible(announce, nexthop->metric_seqno)) - continue; - - uint32_t metric = nexthop->metric_seqno.metric + gp_babel_neigh_get_cost(ctx, nexthop->neigh); - - if (metric < ret_metric) { - ret = nexthop; - ret_metric = metric; - } - } - - return ret; -} - -gp_babel_metric_seqno_t get_metric(gmrf_context_t *ctx, const gp_babel_announce_t *announce) { - if (announce->selected) { - uint32_t metric = announce->selected->metric_seqno.metric + gp_babel_neigh_get_cost(ctx, announce->selected->neigh); - - if (metric < GP_BABEL_INFINITY) - return (gp_babel_metric_seqno_t){metric, announce->selected->metric_seqno.seqno}; - } - - return (gp_babel_metric_seqno_t){GP_BABEL_INFINITY, 0}; -} - -void gp_babel_announce_update(gmrf_context_t *ctx, gp_babel_announce_t *announce) { - maintain_nexthops(ctx, announce); - - announce->selected = select_nexthop(ctx, announce); - announce->metric = get_metric(ctx, announce); - - if (!announce->selected) - gp_babel_send_seqno_request_for(ctx, NULL, announce); - - /* triggered updates */ - /*int diff = announce->metric.metric - announce->last_metric; - - if (((announce->last_metric == GP_BABEL_INFINITY) != (announce->metric.metric == GP_BABEL_INFINITY)) - || diff <= -1024 || diff >= 384) { - gmrf_logf(gmrf, LOG_INFO, "announce metric has changed significantly, sending updates"); - gp_babel_update_enqueue(&announce->node, announce->type, announce->key, NULL, announce->metric.metric == GP_BABEL_INFINITY); - } */ -} - -void gp_babel_announce_update_nexthop(gmrf_context_t *ctx, gp_babel_announce_t *announce, gp_babel_nexthop_t *nexthop, gp_babel_metric_seqno_t ms, uint16_t interval) { - nexthop->metric_seqno = ms; - nexthop->interval = interval; - nexthop->requested_update = false; - - if (ms.metric != GP_BABEL_INFINITY) - nexthop->last_update = gmrf_now(ctx->gmrf); - - gp_babel_announce_update(ctx, announce); -} diff --git a/src/babel.c b/src/babel.c index 7cf52b6..06c972f 100644 --- a/src/babel.c +++ b/src/babel.c @@ -48,7 +48,7 @@ static void send_updates(gmrf_context_t *ctx, void *arg) { gmrf_iface_state_t *iface; for (iface = ctx->interfaces; iface; iface = iface->next) { - gp_babel_send_update(ctx, iface, NULL, NULL, false); + gp_babel_send_update(ctx, iface, NULL); } } @@ -77,28 +77,28 @@ static void maintain_neighbours(gmrf_context_t *ctx) { } } -static void maintain_announces(gmrf_context_t *ctx) { - gp_babel_announce_t **cur, **next; - for (cur = &ctx->announces; *cur; cur = next) { - gp_babel_announce_t *announce = *cur; - next = &announce->next; +static void maintain_routes(gmrf_context_t *ctx) { + gp_babel_route_t **cur, **next; + for (cur = &ctx->routes; *cur; cur = next) { + gp_babel_route_t *route = *cur; + next = &route->next; - gp_babel_announce_update(ctx, announce); + gp_babel_route_update(ctx, route); - if (!announce->nexthops) { + if (!route->nexthops) { *cur = *next; next = cur; - gp_babel_announce_free(ctx, announce); + gp_babel_route_free(ctx, route); continue; } - gmrf_logf(ctx->gmrf, LOG_DEBUG, "node %04x%04x, type %04x, announce %04x (%u, seqno=%04x):", - ntohl(*(uint32_t*)announce->node.id), ntohl(*(uint32_t*)(announce->node.id+4)), - announce->type, announce->key, announce->metric.metric, announce->metric.seqno); + gmrf_logf(ctx->gmrf, LOG_DEBUG, "node %04x%04x (%u, seqno=%04x):", + ntohl(*(uint32_t*)route->node.id), ntohl(*(uint32_t*)(route->node.id+4)), + route->metric.metric, route->metric.seqno); gp_babel_nexthop_t *nexthop; - for (nexthop = announce->nexthops; nexthop; nexthop = nexthop->next) { + for (nexthop = route->nexthops; nexthop; nexthop = nexthop->next) { gp_babel_neigh_t *neigh = nexthop->neigh; if (!neigh) { @@ -111,7 +111,7 @@ static void maintain_announces(gmrf_context_t *ctx) { neigh->addr.d[4], neigh->addr.d[5], neigh->addr.d[6], neigh->addr.d[7], neigh->iface ? gmrf_iface_get_name(ctx->gmrf, neigh->iface->gmrf_iface) : NULL, nexthop->metric_seqno.metric, nexthop->metric_seqno.seqno, gp_babel_neigh_get_cost(ctx, neigh), - (nexthop == announce->selected) ? ", selected" : ""); + (nexthop == route->selected) ? ", selected" : ""); } } } @@ -120,7 +120,7 @@ static void maintenance(gmrf_context_t *ctx, void *arg) { gmrf_schedule(ctx->gmrf, maintenance, NULL, GP_BABEL_MAINTENANCE_INTERVAL*10); maintain_neighbours(ctx); - maintain_announces(ctx); + maintain_routes(ctx); } gmrf_context_t* gmrf_protocol_init(gmrf_t *gmrf) { @@ -135,12 +135,10 @@ gmrf_context_t* gmrf_protocol_init(gmrf_t *gmrf) { ctx->gmrf = gmrf; gmrf_random_bytes(gmrf, &ctx->self, sizeof(gp_babel_node_id_t)); - gp_babel_announce_t *announce = gp_babel_announce_new(ctx); - announce->node = ctx->self; - announce->type = 1; - announce->key = 1337; + gp_babel_route_t *route = gp_babel_route_new(ctx); + route->node = ctx->self; - announce->nexthops = announce->selected = calloc(1, sizeof(gp_babel_nexthop_t)); + route->nexthops = route->selected = calloc(1, sizeof(gp_babel_nexthop_t)); return ctx; } diff --git a/src/babel.h b/src/babel.h index 41db13d..93a3bcd 100644 --- a/src/babel.h +++ b/src/babel.h @@ -50,10 +50,6 @@ #define GP_BABEL_SEQNO_REQ_HOP_LIMIT 127 -#define GP_BABEL_UPDATE_FLAG_HAS_PAYLOAD 0x01 -#define GP_BABEL_ANNOUCE_REQ_FLAG_WITH_PAYLOAD 0x01 - - struct gmrf_context { gmrf_t *gmrf; @@ -62,7 +58,7 @@ struct gmrf_context { gmrf_iface_state_t *interfaces; gp_babel_neigh_t *neighbours; - gp_babel_announce_t *announces; + gp_babel_route_t *routes; }; struct gmrf_iface_state { @@ -94,12 +90,10 @@ struct gp_babel_neigh { uint16_t txcost; }; -struct gp_babel_announce { - gp_babel_announce_t *next; +struct gp_babel_route { + gp_babel_route_t *next; gp_babel_node_id_t node; - uint16_t type; - uint16_t key; gp_babel_metric_seqno_t metric; uint16_t last_metric; @@ -107,10 +101,6 @@ struct gp_babel_announce { gp_babel_nexthop_t *selected; gp_babel_nexthop_t *nexthops; - - /* an incomplete announcement is specified by a len value of 0xff with NULL payload */ - uint8_t len; - uint8_t *payload; }; struct gp_babel_nexthop { @@ -130,20 +120,22 @@ void gp_babel_handle_packet(gmrf_context_t *ctx, gmrf_iface_state_t *iface, cons void gp_babel_send_ack(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, uint16_t nonce); void gp_babel_send_hellos(gmrf_context_t *ctx); -void gp_babel_send_update(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, gp_babel_announce_t *announce, bool with_payload); +void gp_babel_send_update(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh); +void gp_babel_send_update_for_route(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, gp_babel_route_t *route); +void gp_babel_send_retract(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, const gp_babel_node_id_t *node); -void gp_babel_send_announce_request(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, const gp_babel_node_id_t *node, uint16_t type, uint16_t key, bool with_payload); -void gp_babel_send_seqno_request(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, gp_babel_announce_t *announce, uint16_t seqno, uint8_t hop_count); +void gp_babel_send_route_request(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, const gp_babel_node_id_t *node); +void gp_babel_send_seqno_request(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, gp_babel_route_t *route, uint16_t seqno, uint8_t hop_count); -gp_babel_announce_t* gp_babel_announce_new(gmrf_context_t *ctx); -gp_babel_announce_t* gp_babel_announce_find(gmrf_context_t *ctx, const gp_babel_node_id_t *node, uint16_t type, uint16_t key); -gp_babel_announce_t* gp_babel_announce_get(gmrf_context_t *ctx, const gp_babel_node_id_t *node, uint16_t type, uint16_t key); -void gp_babel_announce_update(gmrf_context_t *ctx, gp_babel_announce_t *announce); -void gp_babel_announce_free(gmrf_context_t *ctx, gp_babel_announce_t *announce); +gp_babel_route_t* gp_babel_route_new(gmrf_context_t *ctx); +gp_babel_route_t* gp_babel_route_find(gmrf_context_t *ctx, const gp_babel_node_id_t *node); +gp_babel_route_t* gp_babel_route_get(gmrf_context_t *ctx, const gp_babel_node_id_t *node); +void gp_babel_route_update(gmrf_context_t *ctx, gp_babel_route_t *route); +void gp_babel_route_free(gmrf_context_t *ctx, gp_babel_route_t *route); -gp_babel_nexthop_t* gp_babel_announce_nexthop_new(gp_babel_announce_t *announce, gp_babel_neigh_t *neigh); -gp_babel_nexthop_t* gp_babel_announce_nexthop_find(const gp_babel_announce_t *announce, gp_babel_neigh_t *neigh); -void gp_babel_announce_update_nexthop(gmrf_context_t *ctx, gp_babel_announce_t *announce, gp_babel_nexthop_t *nexthop, gp_babel_metric_seqno_t ms, uint16_t interval); +gp_babel_nexthop_t* gp_babel_route_nexthop_new(gp_babel_route_t *route, gp_babel_neigh_t *neigh); +gp_babel_nexthop_t* gp_babel_route_nexthop_find(const gp_babel_route_t *route, gp_babel_neigh_t *neigh); +void gp_babel_route_update_nexthop(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop, gp_babel_metric_seqno_t ms, uint16_t interval); static inline bool gp_babel_node_id_equal(const gp_babel_node_id_t *id1, const gp_babel_node_id_t *id2) { @@ -177,18 +169,22 @@ static inline bool gp_babel_is_metric_better(gp_babel_metric_seqno_t ms1, gp_bab return false; } -static inline bool gp_babel_is_feasible(const gp_babel_announce_t *announce, gp_babel_metric_seqno_t ms) { +static inline bool gp_babel_route_is_reachable(const gp_babel_route_t *route) { + return (route->metric.metric != GP_BABEL_INFINITY); +} + +static inline bool gp_babel_is_feasible(const gp_babel_route_t *route, gp_babel_metric_seqno_t ms) { if (ms.metric == GP_BABEL_INFINITY) return true; - return gp_babel_is_metric_better(ms, announce->feasibility_distance); + return gp_babel_is_metric_better(ms, route->feasibility_distance); } -static inline void gp_babel_send_seqno_request_for(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, gp_babel_announce_t *announce) { - if (announce->feasibility_distance.metric == GP_BABEL_INFINITY) +static inline void gp_babel_send_seqno_request_for(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, gp_babel_route_t *route) { + if (route->feasibility_distance.metric == GP_BABEL_INFINITY) return; - gp_babel_send_seqno_request(ctx, neigh, announce, announce->feasibility_distance.seqno+1, GP_BABEL_SEQNO_REQ_HOP_LIMIT); + gp_babel_send_seqno_request(ctx, neigh, route, route->feasibility_distance.seqno+1, GP_BABEL_SEQNO_REQ_HOP_LIMIT); } #endif /* _GMRF_PROTO_BABEL_BABEL_H_ */ diff --git a/src/neigh.c b/src/neigh.c index 252713c..0270192 100644 --- a/src/neigh.c +++ b/src/neigh.c @@ -105,6 +105,6 @@ uint16_t gp_babel_neigh_get_cost(gmrf_context_t *ctx, const gp_babel_neigh_t *ne return cost; } -void gp_babel_neigh_reset(gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh) { - //gp_babel_send_announce_request(iface, neigh, GMRF_PROTO_BABEL_NODE_ID_UNSPEC, 0, 0, true /* XXX change this later */); +void gp_babel_neigh_reset(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh) { + gp_babel_send_route_request(ctx, iface, neigh, NULL); } diff --git a/src/neigh.h b/src/neigh.h index 54b935e..713c10d 100644 --- a/src/neigh.h +++ b/src/neigh.h @@ -52,6 +52,6 @@ void gp_babel_neigh_unref_list(gp_babel_neigh_t *neigh); uint16_t gp_babel_neigh_get_rxcost(gmrf_context_t *ctx, const gp_babel_neigh_t *neigh); uint16_t gp_babel_neigh_get_txcost(gmrf_context_t *ctx, const gp_babel_neigh_t *neigh); uint16_t gp_babel_neigh_get_cost(gmrf_context_t *ctx, const gp_babel_neigh_t *neigh); -void gp_babel_neigh_reset(gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh); +void gp_babel_neigh_reset(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh); #endif /* _GMRF_PROTO_BABEL_NEIGH_H_ */ diff --git a/src/route.c b/src/route.c new file mode 100644 index 0000000..91b4944 --- /dev/null +++ b/src/route.c @@ -0,0 +1,199 @@ +/* + Copyright (c) 2013, 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 "babel.h" +#include "neigh.h" + +#include + + +gp_babel_route_t* gp_babel_route_new(gmrf_context_t *ctx) { + gp_babel_route_t *a = calloc(1, sizeof(gp_babel_route_t)); + + a->metric.metric = a->feasibility_distance.metric = a->last_metric = GP_BABEL_INFINITY; + + a->next = ctx->routes; + ctx->routes = a; + + return a; +} + +gp_babel_route_t* gp_babel_route_find(gmrf_context_t *ctx, const gp_babel_node_id_t *node) { + gp_babel_route_t *route; + for (route = ctx->routes; route; route = route->next) { + if (gp_babel_node_id_equal(&route->node, node)) + return route; + } + + return NULL; +} + +gp_babel_route_t* gp_babel_route_get(gmrf_context_t *ctx, const gp_babel_node_id_t *node) { + gp_babel_route_t *route = gp_babel_route_find(ctx, node); + + if (!route) { + route = gp_babel_route_new(ctx); + route->node = *node; + } + + return route; +} + +void gp_babel_route_free(gmrf_context_t *ctx, gp_babel_route_t *route) { + free(route); +} + +gp_babel_nexthop_t* gp_babel_route_nexthop_find(const gp_babel_route_t *route, gp_babel_neigh_t *neigh) { + gp_babel_nexthop_t *nexthop; + for (nexthop = route->nexthops; nexthop; nexthop = nexthop->next) { + if (nexthop->neigh == neigh) + return nexthop; + } + + return NULL; +} + +gp_babel_nexthop_t* gp_babel_route_nexthop_new(gp_babel_route_t *route, gp_babel_neigh_t *neigh) { + gp_babel_nexthop_t *nexthop = calloc(1, sizeof(gp_babel_nexthop_t)); + nexthop->neigh = neigh; + + nexthop->next = route->nexthops; + route->nexthops = nexthop; + + gp_babel_neigh_ref(neigh); + + return nexthop; +} + +static void maintain_nexthops(gmrf_context_t *ctx, gp_babel_route_t *route) { + gp_babel_nexthop_t **cur, **next; + for (cur = &route->nexthops; *cur; cur = next) { + gp_babel_nexthop_t *nexthop = *cur; + next = &nexthop->next; + + if (!nexthop->neigh) /* local */ + continue; + + if (!nexthop->neigh->iface) { + if (nexthop->metric_seqno.metric != GP_BABEL_INFINITY) { + nexthop->metric_seqno.metric = GP_BABEL_INFINITY; + nexthop->last_update = gmrf_now(ctx->gmrf); + nexthop->last_update += GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10; + } + + continue; + } + + if (gmrf_now(ctx->gmrf) > nexthop->last_update+GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10) { + if (nexthop->metric_seqno.metric == GP_BABEL_INFINITY) { + *cur = *next; + next = cur; + + if (route->selected == nexthop) + route->selected = NULL; + + gp_babel_neigh_unref(nexthop->neigh); + + free(nexthop); + } + else { + nexthop->metric_seqno.metric = GP_BABEL_INFINITY; + nexthop->last_update += GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10; + } + } + else if (gmrf_now(ctx->gmrf) > nexthop->last_update+GP_BABEL_UPDATE_REQUEST_TIMEOUT(nexthop->interval)*10 && route->selected == nexthop) { + if (!nexthop->requested_update) { + gmrf_logf(ctx->gmrf, LOG_INFO, "route about to expire, requesting update"); + gp_babel_send_route_request(ctx, NULL, nexthop->neigh, &route->node); + nexthop->requested_update = true; + } + } + } +} + +static gp_babel_nexthop_t* select_nexthop(gmrf_context_t *ctx, const gp_babel_route_t *route) { + uint16_t ret_metric = GP_BABEL_INFINITY; + gp_babel_nexthop_t *ret = NULL; + + gp_babel_nexthop_t *nexthop; + for (nexthop = route->nexthops; nexthop; nexthop = nexthop->next) { + if (!nexthop->neigh) /* local */ + return nexthop; + + if (!gp_babel_is_feasible(route, nexthop->metric_seqno)) + continue; + + uint32_t metric = nexthop->metric_seqno.metric + gp_babel_neigh_get_cost(ctx, nexthop->neigh); + + if (metric < ret_metric) { + ret = nexthop; + ret_metric = metric; + } + } + + return ret; +} + +gp_babel_metric_seqno_t get_metric(gmrf_context_t *ctx, const gp_babel_route_t *route) { + if (route->selected) { + uint32_t metric = route->selected->metric_seqno.metric + gp_babel_neigh_get_cost(ctx, route->selected->neigh); + + if (metric < GP_BABEL_INFINITY) + return (gp_babel_metric_seqno_t){metric, route->selected->metric_seqno.seqno}; + } + + return (gp_babel_metric_seqno_t){GP_BABEL_INFINITY, 0}; +} + +void gp_babel_route_update(gmrf_context_t *ctx, gp_babel_route_t *route) { + maintain_nexthops(ctx, route); + + route->selected = select_nexthop(ctx, route); + route->metric = get_metric(ctx, route); + + if (!route->selected) + gp_babel_send_seqno_request_for(ctx, NULL, route); + + /* triggered updates */ + /*int diff = route->metric.metric - route->last_metric; + + if (((route->last_metric == GP_BABEL_INFINITY) != (route->metric.metric == GP_BABEL_INFINITY)) + || diff <= -1024 || diff >= 384) { + gmrf_logf(gmrf, LOG_INFO, "route metric has changed significantly, sending updates"); + gp_babel_update_enqueue(&route->node, route->type, route->key, NULL, route->metric.metric == GP_BABEL_INFINITY); + } */ +} + +void gp_babel_route_update_nexthop(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop, gp_babel_metric_seqno_t ms, uint16_t interval) { + nexthop->metric_seqno = ms; + nexthop->interval = interval; + nexthop->requested_update = false; + + if (ms.metric != GP_BABEL_INFINITY) + nexthop->last_update = gmrf_now(ctx->gmrf); + + gp_babel_route_update(ctx, route); +} diff --git a/src/send.c b/src/send.c index 9f53510..55adb21 100644 --- a/src/send.c +++ b/src/send.c @@ -30,6 +30,8 @@ #include "tlv.h" #include "tlv_types.h" +#include + static inline bool send_neigh(gmrf_context_t *ctx, const gp_babel_neigh_t *neigh, const gp_babel_packet_t *packet) { if (!neigh->iface) @@ -111,7 +113,7 @@ void gp_babel_send_hellos(gmrf_context_t *ctx) { } } -static inline bool add_node_id(gp_babel_packet_buf_t *buf, const gp_babel_node_id_t *node_id) { +/*static inline bool add_node_id_tlv(gp_babel_packet_buf_t *buf, const gp_babel_node_id_t *node_id) { gp_babel_tlv_node_id_t *tlv = gp_babel_tlv_add(buf, TLV_NODE_ID, sizeof(gp_babel_tlv_node_id_t)); if (!tlv) return false; @@ -119,81 +121,56 @@ static inline bool add_node_id(gp_babel_packet_buf_t *buf, const gp_babel_node_i tlv->id = *node_id; return true; -} - -static bool add_update(gp_babel_packet_buf_t *buf, gp_babel_node_id_t *node_id, gp_babel_announce_t *announce, bool with_payload, bool targetted) { - if (announce->len && !announce->payload) { - /* incomplete announce, handle like non-existent announce */ - return true; - } - - uint16_t len = buf->packet.len; - - if (!node_id || !gp_babel_node_id_equal(node_id, &announce->node)) { - if (!add_node_id(buf, &announce->node)) - return false; + }*/ - if (node_id) - *node_id = announce->node; - } +static gp_babel_tlv_update_t* add_update_tlv(gp_babel_packet_buf_t *buf, const gp_babel_node_id_t *node, gp_babel_metric_seqno_t ms) { + gp_babel_tlv_update_t *update = gp_babel_tlv_add(buf, TLV_UPDATE, sizeof(gp_babel_tlv_update_t)); - uint8_t payload_len = (with_payload && announce->metric.metric != GP_BABEL_INFINITY) ? announce->len : 0; - gp_babel_tlv_update_t *update = gp_babel_tlv_add(buf, TLV_UPDATE, sizeof(gp_babel_tlv_update_t)+payload_len); - if (!update) { - /* reset length to remove possibly added node ID record */ - buf->packet.len = len; - return false; - } + if (!update) + return NULL; update->flags = 0; update->reserved = 0; update->interval = htons(GP_BABEL_UPDATE_INTERVAL); - update->seqno = htons(announce->metric.seqno); - update->metric = htons(announce->metric.metric); - update->type = htons(announce->type); - update->key = htons(announce->key); + update->seqno = htons(ms.seqno); + update->metric = htons(ms.metric); + update->node = *node; - if (announce->metric.metric != GP_BABEL_INFINITY && announce->len) { - update->flags |= GP_BABEL_UPDATE_FLAG_HAS_PAYLOAD; + return update; +} - if (payload_len) - memcpy(update->payload, announce->payload, payload_len); - } +static gp_babel_tlv_update_t* add_retract_tlv(gp_babel_packet_buf_t *buf, const gp_babel_node_id_t *node) { + return add_update_tlv(buf, node, (gp_babel_metric_seqno_t){GP_BABEL_INFINITY, 0}); +} + +static bool add_update(gp_babel_packet_buf_t *buf, gp_babel_route_t *route, bool targetted) { + gp_babel_tlv_update_t *update = add_update_tlv(buf, &route->node, route->metric); + if (!update) + return false; - if (gp_babel_is_metric_better(announce->metric, announce->feasibility_distance)) - announce->feasibility_distance = announce->metric; + if (gp_babel_is_metric_better(route->metric, route->feasibility_distance)) + route->feasibility_distance = route->metric; if (!targetted) - announce->last_metric = announce->metric.metric; + route->last_metric = route->metric.metric; return true; } -void gp_babel_send_update(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, gp_babel_announce_t *announce, bool with_payload) { +void gp_babel_send_update(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh) { gp_babel_packet_buf_t *buf = gp_babel_packet_alloca(GP_BABEL_PACKET_MAX); - if (announce) { - add_update(buf, NULL, announce, with_payload, neigh); - } - else { - gp_babel_node_id_t node_id = gp_babel_node_id_unspec; - - gp_babel_announce_t *a; - for (a = ctx->announces; a; a = a->next) { - if (!add_update(buf, &node_id, a, with_payload, neigh)) { - if (neigh) - send_neigh(ctx, neigh, &buf->packet); - else - send_iface(ctx, iface, &buf->packet); - - node_id = gp_babel_node_id_unspec; - buf->packet.len = 0; - - if (!add_update(buf, &node_id, a, with_payload, neigh)) { - gmrf_logf(ctx->gmrf, LOG_ERR, "add_update failed"); - return; - } - } + gp_babel_route_t *a; + for (a = ctx->routes; a; a = a->next) { + if (!add_update(buf, a, neigh)) { + if (neigh) + send_neigh(ctx, neigh, &buf->packet); + else + send_iface(ctx, iface, &buf->packet); + + buf->packet.len = 0; + + assert(add_update(buf, a, neigh)); } } @@ -205,21 +182,39 @@ void gp_babel_send_update(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_bab } } -void gp_babel_send_announce_request(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, const gp_babel_node_id_t *node, uint16_t type, uint16_t key, bool with_payload) { +void gp_babel_send_update_for_route(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, gp_babel_route_t *route) { gp_babel_packet_buf_t *buf = gp_babel_packet_alloca(GP_BABEL_PACKET_MAX); - gp_babel_tlv_announce_req_t *req = gp_babel_tlv_add(buf, TLV_ANNOUNCE_REQ, sizeof(gp_babel_tlv_announce_req_t)); + assert(add_update(buf, route, neigh)); + + if (neigh) + send_neigh(ctx, neigh, &buf->packet); + else + send_iface(ctx, iface, &buf->packet); +} + +void gp_babel_send_retract(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, const gp_babel_node_id_t *node) { + gp_babel_packet_buf_t *buf = gp_babel_packet_alloca(GP_BABEL_PACKET_MAX); + + assert(add_retract_tlv(buf, node)); + + if (neigh) + send_neigh(ctx, neigh, &buf->packet); + else + send_iface(ctx, iface, &buf->packet); +} + +void gp_babel_send_route_request(gmrf_context_t *ctx, gmrf_iface_state_t *iface, gp_babel_neigh_t *neigh, const gp_babel_node_id_t *node) { + gp_babel_packet_buf_t *buf = gp_babel_packet_alloca(GP_BABEL_PACKET_MAX); + + gp_babel_tlv_route_req_t *req = gp_babel_tlv_add(buf, TLV_ROUTE_REQ, sizeof(gp_babel_tlv_route_req_t)); if (!req) return; - req->node = *node; + req->node = node ? (*node) : (gp_babel_node_id_t){}; + req->flags = 0; req->reserved = 0; - req->type = htons(type); - req->key = htons(key); - - if (with_payload) - req->flags |= GP_BABEL_ANNOUCE_REQ_FLAG_WITH_PAYLOAD; if (neigh) send_neigh(ctx, neigh, &buf->packet); @@ -227,7 +222,7 @@ void gp_babel_send_announce_request(gmrf_context_t *ctx, gmrf_iface_state_t *ifa send_iface(ctx, iface, &buf->packet); } -void gp_babel_send_seqno_request(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, gp_babel_announce_t *announce, uint16_t seqno, uint8_t hop_count) { +void gp_babel_send_seqno_request(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, gp_babel_route_t *route, uint16_t seqno, uint8_t hop_count) { gp_babel_packet_buf_t *buf = gp_babel_packet_alloca(GP_BABEL_PACKET_MAX); gp_babel_tlv_seqno_req_t *req = gp_babel_tlv_add(buf, TLV_SEQNO_REQ, sizeof(gp_babel_tlv_seqno_req_t)); @@ -237,9 +232,7 @@ void gp_babel_send_seqno_request(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, g req->seqno = htons(seqno); req->hop_count = hop_count; req->reserved = 0; - req->node = announce->node; - req->type = htons(announce->type); - req->key = htons(announce->key); + req->node = route->node; if (neigh) send_neigh(ctx, neigh, &buf->packet); diff --git a/src/tlv.h b/src/tlv.h index baf10e1..2cfd73d 100644 --- a/src/tlv.h +++ b/src/tlv.h @@ -40,7 +40,7 @@ typedef enum gp_babel_tlv_type { TLV_NODE_ID, TLV_RESERVED, TLV_UPDATE, - TLV_ANNOUNCE_REQ, + TLV_ROUTE_REQ, TLV_SEQNO_REQ, } gp_babel_tlv_type_t; diff --git a/src/tlv_types.c b/src/tlv_types.c index 5f077db..bd68642 100644 --- a/src/tlv_types.c +++ b/src/tlv_types.c @@ -43,25 +43,25 @@ static inline gp_babel_neigh_t* get_tlv_neigh(handle_tlv_arg_t *arg) { return gp_babel_neigh_get(arg->iface, arg->source); } -static void handle_tlv_ack_req(gmrf_context_t *ctx, const gp_babel_tlv_ack_req_t *tlv_req, size_t len, handle_tlv_arg_t *arg) { +static void handle_tlv_ack_req(gmrf_context_t *ctx, const gp_babel_tlv_ack_req_t *tlv, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(gp_babel_tlv_ack_req_t)) { gmrf_logf(ctx->gmrf, LOG_WARNING, "received short acknowledement request TLV."); return; } - gp_babel_send_ack(ctx, get_tlv_neigh(arg), ntohs(tlv_req->nonce)); + gp_babel_send_ack(ctx, get_tlv_neigh(arg), ntohs(tlv->nonce)); } -static void handle_tlv_ack(gmrf_context_t *ctx, const gp_babel_tlv_ack_t *tlv_ack, size_t len, handle_tlv_arg_t *arg) { +static void handle_tlv_ack(gmrf_context_t *ctx, const gp_babel_tlv_ack_t *tlv, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(gp_babel_tlv_ack_t)) { gmrf_logf(ctx->gmrf, LOG_WARNING, "received short acknowledement TLV."); return; } - //gp_babel_ack_handle(ntohs(tlv_ack->nonce)); + //gp_babel_ack_handle(ntohs(tlv->nonce)); } -static void handle_tlv_hello(gmrf_context_t *ctx, const gp_babel_tlv_hello_t *tlv_hello, size_t len, handle_tlv_arg_t *arg) { +static void handle_tlv_hello(gmrf_context_t *ctx, const gp_babel_tlv_hello_t *tlv, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(gp_babel_tlv_hello_t)) { gmrf_logf(ctx->gmrf, LOG_WARNING, "received short hello TLV."); return; @@ -70,11 +70,11 @@ static void handle_tlv_hello(gmrf_context_t *ctx, const gp_babel_tlv_hello_t *tl gmrf_logf(ctx->gmrf, LOG_DEBUG, "received hello from %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x[%s] with seqno %04x.", arg->source->d[0], arg->source->d[1], arg->source->d[2], arg->source->d[3], arg->source->d[4], arg->source->d[5], arg->source->d[6], arg->source->d[7], - gmrf_iface_get_name(ctx->gmrf, arg->iface->gmrf_iface), ntohs(tlv_hello->seqno)); + gmrf_iface_get_name(ctx->gmrf, arg->iface->gmrf_iface), ntohs(tlv->seqno)); gp_babel_neigh_t *neigh = get_tlv_neigh(arg); - uint16_t seqno = ntohs(tlv_hello->seqno); + uint16_t seqno = ntohs(tlv->seqno); if (neigh->last_hello != gmrf_time_unspec) { int timediff = (gmrf_now(ctx->gmrf) - neigh->last_hello)/10; @@ -101,112 +101,92 @@ static void handle_tlv_hello(gmrf_context_t *ctx, const gp_babel_tlv_hello_t *tl } neigh->hello_log |= 1; - neigh->hello_interval = ntohs(tlv_hello->interval); + neigh->hello_interval = ntohs(tlv->interval); neigh->last_seqno = seqno; neigh->last_hello = gmrf_now(ctx->gmrf); if (neigh->hello_log == 1) /* new or reset neighbour */ - gp_babel_neigh_reset(arg->iface, neigh); + gp_babel_neigh_reset(ctx, arg->iface, neigh); gmrf_logf(ctx->gmrf, LOG_DEBUG, "accepted hello, log %04x, rxcost is %u, cost is %u now.", neigh->hello_log, gp_babel_neigh_get_rxcost(ctx, neigh), gp_babel_neigh_get_cost(ctx, neigh)); } -static void handle_tlv_ihu(gmrf_context_t *ctx, const gp_babel_tlv_ihu_t *tlv_ihu, size_t len, handle_tlv_arg_t *arg) { +static void handle_tlv_ihu(gmrf_context_t *ctx, const gp_babel_tlv_ihu_t *tlv, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(gp_babel_tlv_ihu_t)) { gmrf_logf(ctx->gmrf, LOG_WARNING, "received short IHU TLV."); return; } - if (tlv_ihu->ae == ADDR_ENC_GMRF) { + if (tlv->ae == ADDR_ENC_GMRF) { if (len < sizeof(gp_babel_tlv_ihu_t)+sizeof(gmrf_addr_t)) { gmrf_logf(ctx->gmrf, LOG_WARNING, "received short IHU TLV."); return; } gmrf_addr_t iface_addr = gmrf_iface_get_addr(ctx->gmrf, arg->iface->gmrf_iface); - if (memcmp(tlv_ihu->address, &iface_addr, sizeof(gmrf_addr_t)) != 0) + if (memcmp(tlv->address, &iface_addr, sizeof(gmrf_addr_t)) != 0) return; } - else if (tlv_ihu->ae != ADDR_ENC_UNSPEC) { + else if (tlv->ae != ADDR_ENC_UNSPEC) { return; } gp_babel_neigh_t *neigh = get_tlv_neigh(arg); - neigh->ihu_interval = ntohs(tlv_ihu->interval); + neigh->ihu_interval = ntohs(tlv->interval); neigh->last_ihu = gmrf_now(ctx->gmrf); - neigh->txcost = ntohs(tlv_ihu->rxcost); + neigh->txcost = ntohs(tlv->rxcost); gmrf_logf(ctx->gmrf, LOG_DEBUG, "accepted IHU, txcost is %u, cost is %u now.", gp_babel_neigh_get_txcost(ctx, neigh), gp_babel_neigh_get_cost(ctx, neigh)); } -static void handle_tlv_node_id(gmrf_context_t *ctx, const gp_babel_tlv_node_id_t *tlv_node_id, size_t len, handle_tlv_arg_t *arg) { +static void handle_tlv_node_id(gmrf_context_t *ctx, const gp_babel_tlv_node_id_t *tlv, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(gp_babel_tlv_node_id_t)) { gmrf_logf(ctx->gmrf, LOG_WARNING, "received short node id TLV."); return; } - arg->node_id = tlv_node_id->id; + arg->node_id = tlv->id; } -static void handle_tlv_update(gmrf_context_t *ctx, const gp_babel_tlv_update_t *tlv_update, size_t len, handle_tlv_arg_t *arg) { +static void handle_tlv_update(gmrf_context_t *ctx, const gp_babel_tlv_update_t *tlv, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(gp_babel_tlv_update_t)) { gmrf_logf(ctx->gmrf, LOG_WARNING, "received short update TLV."); return; } - if (gp_babel_node_id_is_unspec(&arg->node_id)) { - gmrf_logf(ctx->gmrf, LOG_WARNING, "received update TLV without node id TLV."); - return; - } - - if (gp_babel_node_id_equal(&arg->node_id, &ctx->self)) { + if (gp_babel_node_id_equal(&tlv->node, &ctx->self)) { gmrf_logf(ctx->gmrf, LOG_DEBUG, "update source is myself."); return; } - gp_babel_announce_t *announce = gp_babel_announce_get(ctx, &arg->node_id, ntohs(tlv_update->type), ntohs(tlv_update->key)); - gp_babel_metric_seqno_t ms = { ntohs(tlv_update->metric), ntohs(tlv_update->seqno) }; - bool feasible = gp_babel_is_feasible(announce, ms); + gp_babel_route_t *route = gp_babel_route_get(ctx, &tlv->node); + gp_babel_metric_seqno_t ms = { ntohs(tlv->metric), ntohs(tlv->seqno) }; + bool feasible = gp_babel_is_feasible(route, ms); gp_babel_neigh_t *neigh = get_tlv_neigh(arg); - gp_babel_nexthop_t *nexthop = gp_babel_announce_nexthop_find(announce, neigh); + gp_babel_nexthop_t *nexthop = gp_babel_route_nexthop_find(route, neigh); gmrf_logf(ctx->gmrf, LOG_DEBUG, "update received from %04x%04x, metric %u, seqno %04x.", - ntohl(*(uint32_t*)arg->node_id.id), ntohl(*(uint32_t*)(arg->node_id.id+4)), + ntohl(*(uint32_t*)tlv->node.id), ntohl(*(uint32_t*)(tlv->node.id+4)), ms.metric, ms.seqno); gmrf_logf(ctx->gmrf, LOG_DEBUG, "the update is %sfeasible and there is %s nexthop.", feasible ? "" : "not ", nexthop ? "a" : "no"); if (!nexthop) { - if (feasible && tlv_update->metric != GP_BABEL_INFINITY /* no need to ntohs */) - nexthop = gp_babel_announce_nexthop_new(announce, neigh); + if (feasible && tlv->metric != GP_BABEL_INFINITY /* no need to ntohs */) + nexthop = gp_babel_route_nexthop_new(route, neigh); } else { - if (!feasible && nexthop == announce->selected) { + if (!feasible && nexthop == route->selected) { gmrf_logf(ctx->gmrf, LOG_DEBUG, "requesting new seqno"); - gp_babel_send_seqno_request_for(ctx, neigh, announce); + gp_babel_send_seqno_request_for(ctx, neigh, route); nexthop = NULL; } } - if (!feasible && nexthop && nexthop != announce->selected) { - if (ms.metric + gp_babel_neigh_get_cost(ctx, neigh) < announce->metric.metric) { + if (!feasible && nexthop && nexthop != route->selected) { + if (ms.metric + gp_babel_neigh_get_cost(ctx, neigh) < route->metric.metric) { gmrf_logf(ctx->gmrf, LOG_DEBUG, "requesting new seqno"); - gp_babel_send_seqno_request_for(ctx, neigh, announce); - } - } - - if ((tlv_update->flags & GP_BABEL_UPDATE_FLAG_HAS_PAYLOAD) && !announce->payload) { - if (len > sizeof(gp_babel_tlv_update_t)) { - announce->len = len - sizeof(gp_babel_tlv_update_t); - announce->payload = malloc(announce->len); - memcpy(announce->payload, tlv_update->payload, announce->len); - } - else { - announce->len = 0xff; - - /* request payload */ - if (nexthop) - gp_babel_send_announce_request(ctx, NULL, neigh, &announce->node, announce->type, announce->key, true); + gp_babel_send_seqno_request_for(ctx, neigh, route); } } @@ -215,56 +195,81 @@ static void handle_tlv_update(gmrf_context_t *ctx, const gp_babel_tlv_update_t * gmrf_logf(ctx->gmrf, LOG_DEBUG, "the update was accepted."); - gp_babel_announce_update_nexthop(ctx, announce, nexthop, ms, ntohs(tlv_update->interval)); + gp_babel_route_update_nexthop(ctx, route, nexthop, ms, ntohs(tlv->interval)); } -static void handle_tlv_seqno_req(gmrf_context_t *ctx, const gp_babel_tlv_seqno_req_t *tlv_seqno_req, size_t len, handle_tlv_arg_t *arg) { +static void handle_tlv_route_req(gmrf_context_t *ctx, const gp_babel_tlv_route_req_t *tlv, size_t len, handle_tlv_arg_t *arg) { + if (len < sizeof(gp_babel_tlv_route_req_t)) { + gmrf_logf(ctx->gmrf, LOG_WARNING, "received short route request TLV."); + return; + } + + const gp_babel_node_id_t *node = &tlv->node; + gp_babel_route_t *route = NULL; + gp_babel_neigh_t *neigh = get_tlv_neigh(arg); + + if (gp_babel_node_id_is_unspec(node)) + node = NULL; + + if (node) { + route = gp_babel_route_find(ctx, &tlv->node); + if (!route) { + gmrf_logf(ctx->gmrf, LOG_DEBUG, "received route request for unknown route, retracting."); + gp_babel_send_retract(ctx, arg->iface, neigh, node); + return; + } + } + + // TODO +} + +static void handle_tlv_seqno_req(gmrf_context_t *ctx, const gp_babel_tlv_seqno_req_t *tlv, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(gp_babel_tlv_seqno_req_t)) { gmrf_logf(ctx->gmrf, LOG_WARNING, "received short seqno request TLV."); return; } - gp_babel_announce_t *announce = gp_babel_announce_get(ctx, &tlv_seqno_req->node, ntohs(tlv_seqno_req->type), ntohs(tlv_seqno_req->key)); - if (!announce || !announce->selected) { - gmrf_logf(ctx->gmrf, LOG_DEBUG, "received seqno request for unknown/unreachable announce."); + gp_babel_route_t *route = gp_babel_route_find(ctx, &tlv->node); + if (!route || !route->selected) { + gmrf_logf(ctx->gmrf, LOG_DEBUG, "received seqno request for unknown/unreachable route."); return; } gmrf_logf(ctx->gmrf, LOG_DEBUG, "seqno request received for %04x%04x, seqno %04x.", - ntohl(*(uint32_t*)tlv_seqno_req->node.id), ntohl(*(uint32_t*)(tlv_seqno_req->node.id+4)), - ntohs(tlv_seqno_req->seqno)); + ntohl(*(uint32_t*)tlv->node.id), ntohl(*(uint32_t*)(tlv->node.id+4)), + ntohs(tlv->seqno)); gp_babel_neigh_t *neigh = get_tlv_neigh(arg); - if (!gp_babel_less(announce->metric.seqno, ntohs(tlv_seqno_req->seqno))) { + if (!gp_babel_less(route->metric.seqno, ntohs(tlv->seqno))) { /* local seqno is high enough */ gmrf_logf(ctx->gmrf, LOG_DEBUG, "sending update."); - gp_babel_send_update(ctx, arg->iface, neigh, announce, false); + gp_babel_send_update_for_route(ctx, arg->iface, neigh, route); return; } - if (!announce->selected->neigh) { - /* announce is local, increment seqno */ + if (!route->selected->neigh) { + /* route is local, increment seqno */ gmrf_logf(ctx->gmrf, LOG_DEBUG, "incrementing seqno."); - announce->selected->metric_seqno.seqno++; + route->selected->metric_seqno.seqno++; - gp_babel_send_update(ctx, arg->iface, neigh, announce, false); + gp_babel_send_update_for_route(ctx, arg->iface, neigh, route); return; } - if (tlv_seqno_req->hop_count < 2) { + if (tlv->hop_count < 2) { gmrf_logf(ctx->gmrf, LOG_DEBUG, "hopcount too low, discarding."); return; } - if (announce->selected->neigh == neigh) { + if (route->selected->neigh == neigh) { gmrf_logf(ctx->gmrf, LOG_DEBUG, "not forwarding backwards."); return; } /* forward request */ gmrf_logf(ctx->gmrf, LOG_DEBUG, "forwarding request."); - gp_babel_send_seqno_request(ctx, announce->selected->neigh, announce, ntohs(tlv_seqno_req->seqno), tlv_seqno_req->hop_count-1); + gp_babel_send_seqno_request(ctx, route->selected->neigh, route, ntohs(tlv->seqno), tlv->hop_count-1); } static void handle_tlv(gmrf_context_t *ctx, gp_babel_tlv_type_t type, const void *data, size_t len, void *arg) { @@ -295,6 +300,10 @@ static void handle_tlv(gmrf_context_t *ctx, gp_babel_tlv_type_t type, const void handle_tlv_update(ctx, data, len, tlv_arg); return; + case TLV_ROUTE_REQ: + handle_tlv_route_req(ctx, data, len, tlv_arg); + return; + case TLV_SEQNO_REQ: handle_tlv_seqno_req(ctx, data, len, tlv_arg); return; diff --git a/src/tlv_types.h b/src/tlv_types.h index 26ddefc..08a23b6 100644 --- a/src/tlv_types.h +++ b/src/tlv_types.h @@ -64,26 +64,21 @@ typedef struct __attribute__((packed)) gp_babel_tlv_update { uint16_t interval; uint16_t seqno; uint16_t metric; - uint16_t type; - uint16_t key; - uint8_t payload[]; + uint16_t version; + gp_babel_node_id_t node; } gp_babel_tlv_update_t; -typedef struct __attribute__((packed)) gp_babel_tlv_announce_req { +typedef struct __attribute__((packed)) gp_babel_tlv_route_req { uint8_t flags; uint8_t reserved; gp_babel_node_id_t node; - uint16_t type; - uint16_t key; -} gp_babel_tlv_announce_req_t; +} gp_babel_tlv_route_req_t; typedef struct __attribute__((packed)) gp_babel_tlv_seqno_req { uint16_t seqno; uint8_t hop_count; uint8_t reserved; gp_babel_node_id_t node; - uint16_t type; - uint16_t key; } gp_babel_tlv_seqno_req_t; #endif /* _GMRF_PROTO_BABEL_TLV_TYPES_H_ */ diff --git a/src/types.h b/src/types.h index d7cd604..0907232 100644 --- a/src/types.h +++ b/src/types.h @@ -46,7 +46,7 @@ typedef struct gp_babel_metric_seqno { typedef struct gp_babel_neigh gp_babel_neigh_t; -typedef struct gp_babel_announce gp_babel_announce_t; +typedef struct gp_babel_route gp_babel_route_t; typedef struct gp_babel_nexthop gp_babel_nexthop_t; typedef struct gp_babel_packet gp_babel_packet_t; -- cgit v1.2.3