Add nexthop data structure and receive updates

This commit is contained in:
Matthias Schiffer 2013-03-24 02:54:17 +01:00
parent a5d0293827
commit 0af36311e1
4 changed files with 119 additions and 0 deletions

View file

@ -25,6 +25,7 @@
#include "babel.h" #include "babel.h"
#include "neigh.h"
#include <stdlib.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) { void gp_babel_announce_free(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_announce_t *announce) {
free(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;
}

View file

@ -94,16 +94,34 @@ struct gp_babel_announce {
uint16_t last_metric; uint16_t last_metric;
gp_babel_metric_seqno_t feasibility_distance; 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 */ /* an incomplete announcement is specified by a len value of 0xff with NULL data */
uint8_t len; uint8_t len;
uint8_t *data; 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) { 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); 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) { static inline gp_babel_iface_t* gp_babel_get_iface(gmrf_context_t *ctx, gmrf_iface_t *gmrf_iface) {
gp_babel_iface_t *iface; gp_babel_iface_t *iface;
for (iface = ctx->interfaces; iface; iface = iface->next) { 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); 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); 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_ */ #endif /* _GMRF_PROTO_BABEL_BABEL_H_ */

View file

@ -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; 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) { 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; 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); handle_tlv_node_id(gmrf, ctx, data, len, tlv_arg);
return; return;
case TLV_UPDATE:
handle_tlv_update(gmrf, ctx, data, len, tlv_arg);
return;
default: default:
gmrf_logf(gmrf, LOG_DEBUG, "received unknown TLV %u on %s.", type, gmrf_iface_get_name(gmrf, tlv_arg->iface->gmrf_iface)); gmrf_logf(gmrf, LOG_DEBUG, "received unknown TLV %u on %s.", type, gmrf_iface_get_name(gmrf, tlv_arg->iface->gmrf_iface));
return; return;

View file

@ -48,6 +48,7 @@ typedef struct gp_babel_metric_seqno {
typedef struct gp_babel_iface gp_babel_iface_t; typedef struct gp_babel_iface gp_babel_iface_t;
typedef struct gp_babel_neigh gp_babel_neigh_t; typedef struct gp_babel_neigh gp_babel_neigh_t;
typedef struct gp_babel_announce gp_babel_announce_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 gp_babel_packet_t;
typedef struct gp_babel_packet_buf gp_babel_packet_buf_t; typedef struct gp_babel_packet_buf gp_babel_packet_buf_t;