From 0af36311e10c0dd480bcfca5774db738e165066d Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 24 Mar 2013 02:54:17 +0100 Subject: Add nexthop data structure and receive updates --- src/announce.c | 23 ++++++++++++++++++ src/babel.h | 21 ++++++++++++++++ src/tlv_types.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/types.h | 1 + 4 files changed, 119 insertions(+) diff --git a/src/announce.c b/src/announce.c index dbe7a4c..1891341 100644 --- a/src/announce.c +++ b/src/announce.c @@ -25,6 +25,7 @@ #include "babel.h" +#include "neigh.h" #include @@ -68,3 +69,25 @@ gp_babel_announce_t* gp_babel_announce_get(gmrf_t *gmrf, gmrf_context_t *ctx, co void gp_babel_announce_free(gmrf_t *gmrf, 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; +} diff --git a/src/babel.h b/src/babel.h index 5870364..3e9b3fd 100644 --- a/src/babel.h +++ b/src/babel.h @@ -94,16 +94,34 @@ struct gp_babel_announce { uint16_t last_metric; gp_babel_metric_seqno_t feasibility_distance; + gp_babel_nexthop_t *selected; + gp_babel_nexthop_t *nexthops; + /* an incomplete announcement is specified by a len value of 0xff with NULL data */ uint8_t len; uint8_t *data; }; +struct gp_babel_nexthop { + gp_babel_nexthop_t *next; + + gp_babel_neigh_t *neigh; + gp_babel_metric_seqno_t metric_seqno; + + gmrf_time_t last_update; + uint16_t interval; + bool requested_update; +}; + static inline bool gp_babel_node_id_equal(const gp_babel_node_id_t *id1, const gp_babel_node_id_t *id2) { return (memcmp(id1->id, id2->id, GP_BABEL_NODE_ID_LENGTH) == 0); } +static inline bool gp_babel_node_id_is_unspec(const gp_babel_node_id_t *id) { + return gp_babel_node_id_equal(id, &gp_babel_node_id_unspec); +}; + static inline gp_babel_iface_t* gp_babel_get_iface(gmrf_context_t *ctx, gmrf_iface_t *gmrf_iface) { gp_babel_iface_t *iface; for (iface = ctx->interfaces; iface; iface = iface->next) { @@ -153,4 +171,7 @@ gp_babel_announce_t* gp_babel_announce_find(gmrf_t *gmrf, gmrf_context_t *ctx, c gp_babel_announce_t* gp_babel_announce_get(gmrf_t *gmrf, gmrf_context_t *ctx, const gp_babel_node_id_t *node, uint16_t type, uint16_t key); void gp_babel_announce_free(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_announce_t *announce); +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); + #endif /* _GMRF_PROTO_BABEL_BABEL_H_ */ diff --git a/src/tlv_types.c b/src/tlv_types.c index 3ff8bf9..b860784 100644 --- a/src/tlv_types.c +++ b/src/tlv_types.c @@ -145,6 +145,76 @@ static void handle_tlv_node_id(gmrf_t *gmrf, gmrf_context_t *ctx, const gp_babel arg->node_id = tlv_node_id->id; } +static void handle_tlv_update(gmrf_t *gmrf, gmrf_context_t *ctx, const gp_babel_tlv_update_t *tlv_update, size_t len, handle_tlv_arg_t *arg) { + if (len < sizeof(gp_babel_tlv_update_t)) { + gmrf_logf(gmrf, LOG_WARNING, "received short update TLV."); + return; + } + + if (gp_babel_node_id_is_unspec(&arg->node_id)) { + gmrf_logf(gmrf, LOG_WARNING, "received update TLV without node id TLV."); + return; + } + + if (gp_babel_node_id_equal(&arg->node_id, &ctx->self)) { + gmrf_logf(gmrf, LOG_DEBUG, "update source is myself."); + return; + } + + gp_babel_announce_t *announce = gp_babel_announce_get(gmrf, 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_neigh_t *neigh = get_tlv_neigh(arg); + gp_babel_nexthop_t *nexthop = gp_babel_announce_nexthop_find(announce, neigh); + + gmrf_logf(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)), + ms.metric, ms.seqno); + gmrf_logf(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); + } + else { + if (!feasible && nexthop == announce->selected) { + gmrf_logf(gmrf, LOG_DEBUG, "need new seqno"); + // gp_babel_send_seqno_request_for(neigh, announce); + nexthop = NULL; + } + } + + if (!feasible && nexthop && nexthop != announce->selected) { + if (ms.metric + gp_babel_neigh_get_cost(gmrf, neigh) < announce->metric.metric) { + gmrf_logf(gmrf, LOG_DEBUG, "need new seqno"); + // gp_babel_send_seqno_request_for(neigh, announce); + } + } + + if (!announce->data) { + if (len > sizeof(gp_babel_tlv_update_t)) { + announce->len = len - sizeof(gp_babel_tlv_update_t); + announce->data = malloc(announce->len); + memcpy(announce->data, tlv_update->data, announce->len); + } + else { + announce->len = 0xff; + + /* request data */ + //if (nexthop) + // gp_babel_send_announce_request(arg->iface, neigh, announce->node, announce->type, announce->key, true); + } + } + + if (!nexthop) + return; + + gmrf_logf(gmrf, LOG_DEBUG, "the update was accepted."); + + //gp_babel_announce_update_nexthop(announce, nexthop, ms, ntohs(tlv_update->interval)); +} + static void handle_tlv(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_tlv_type_t type, const void *data, size_t len, void *arg) { handle_tlv_arg_t *tlv_arg = arg; @@ -169,6 +239,10 @@ static void handle_tlv(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_tlv_type_t ty handle_tlv_node_id(gmrf, ctx, data, len, tlv_arg); return; + case TLV_UPDATE: + handle_tlv_update(gmrf, ctx, data, len, tlv_arg); + return; + default: gmrf_logf(gmrf, LOG_DEBUG, "received unknown TLV %u on %s.", type, gmrf_iface_get_name(gmrf, tlv_arg->iface->gmrf_iface)); return; diff --git a/src/types.h b/src/types.h index a659230..3e38d91 100644 --- a/src/types.h +++ b/src/types.h @@ -48,6 +48,7 @@ typedef struct gp_babel_metric_seqno { typedef struct gp_babel_iface gp_babel_iface_t; typedef struct gp_babel_neigh gp_babel_neigh_t; typedef struct gp_babel_announce gp_babel_announce_t; +typedef struct gp_babel_nexthop gp_babel_nexthop_t; typedef struct gp_babel_packet gp_babel_packet_t; typedef struct gp_babel_packet_buf gp_babel_packet_buf_t; -- cgit v1.2.3