Add nexthop data structure and receive updates
This commit is contained in:
parent
a5d0293827
commit
0af36311e1
4 changed files with 119 additions and 0 deletions
|
@ -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;
|
||||||
|
}
|
||||||
|
|
21
src/babel.h
21
src/babel.h
|
@ -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_ */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Reference in a new issue