summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2013-03-24 02:54:17 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2013-03-24 02:54:17 +0100
commit0af36311e10c0dd480bcfca5774db738e165066d (patch)
tree18d6b161e73f20b33b7505442f14af1e33265a8e
parenta5d0293827874ccce048c8654f58711f807a3e96 (diff)
downloadbabel-0af36311e10c0dd480bcfca5774db738e165066d.tar
babel-0af36311e10c0dd480bcfca5774db738e165066d.zip
Add nexthop data structure and receive updates
-rw-r--r--src/announce.c23
-rw-r--r--src/babel.h21
-rw-r--r--src/tlv_types.c74
-rw-r--r--src/types.h1
4 files changed, 119 insertions, 0 deletions
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 <stdlib.h>
@@ -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;