Add sending of updates
This commit is contained in:
parent
13b755cd43
commit
14f32dfc31
4 changed files with 151 additions and 5 deletions
12
src/babel.c
12
src/babel.c
|
@ -41,6 +41,17 @@ static void send_hellos(gmrf_t *gmrf, gmrf_context_t *ctx, void *arg) {
|
||||||
gp_babel_send_hellos(gmrf, ctx);
|
gp_babel_send_hellos(gmrf, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_updates(gmrf_t *gmrf, gmrf_context_t *ctx, void *arg) {
|
||||||
|
gmrf_schedule(gmrf, send_updates, NULL, GP_BABEL_UPDATE_INTERVAL*10);
|
||||||
|
|
||||||
|
gmrf_logf(gmrf, LOG_DEBUG, "sending periodic updates.");
|
||||||
|
|
||||||
|
gp_babel_iface_t *iface;
|
||||||
|
for (iface = ctx->interfaces; iface; iface = iface->next) {
|
||||||
|
gp_babel_send_update(gmrf, ctx, iface, NULL, NULL, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void maintenance(gmrf_t *gmrf, gmrf_context_t *ctx, void *arg) {
|
static void maintenance(gmrf_t *gmrf, gmrf_context_t *ctx, void *arg) {
|
||||||
gmrf_schedule(gmrf, maintenance, NULL, GP_BABEL_MAINTENANCE_INTERVAL*10);
|
gmrf_schedule(gmrf, maintenance, NULL, GP_BABEL_MAINTENANCE_INTERVAL*10);
|
||||||
|
|
||||||
|
@ -72,6 +83,7 @@ gmrf_context_t* gmrf_protocol_init(gmrf_t *gmrf) {
|
||||||
gmrf_logf(gmrf, LOG_INFO, "initalizing...");
|
gmrf_logf(gmrf, LOG_INFO, "initalizing...");
|
||||||
|
|
||||||
gmrf_schedule(gmrf, send_hellos, NULL, GP_BABEL_HELLO_INTERVAL*10);
|
gmrf_schedule(gmrf, send_hellos, NULL, GP_BABEL_HELLO_INTERVAL*10);
|
||||||
|
gmrf_schedule(gmrf, send_updates, NULL, GP_BABEL_UPDATE_INTERVAL*10);
|
||||||
gmrf_schedule(gmrf, maintenance, NULL, GP_BABEL_MAINTENANCE_INTERVAL*10);
|
gmrf_schedule(gmrf, maintenance, NULL, GP_BABEL_MAINTENANCE_INTERVAL*10);
|
||||||
|
|
||||||
gmrf_context_t *ctx = calloc(1, sizeof(gmrf_context_t));
|
gmrf_context_t *ctx = calloc(1, sizeof(gmrf_context_t));
|
||||||
|
|
33
src/babel.h
33
src/babel.h
|
@ -29,11 +29,16 @@
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define GP_BABEL_INFINITY 0xffff
|
||||||
|
|
||||||
#define GP_BABEL_PACKET_MAX 1000
|
#define GP_BABEL_PACKET_MAX 1000
|
||||||
|
|
||||||
#define GP_BABEL_HELLO_INTERVAL 400
|
#define GP_BABEL_HELLO_INTERVAL 400
|
||||||
#define GP_BABEL_IHU_INTERVAL (3*GP_BABEL_HELLO_INTERVAL)
|
#define GP_BABEL_IHU_INTERVAL (3*GP_BABEL_HELLO_INTERVAL)
|
||||||
|
|
||||||
|
#define GP_BABEL_UPDATE_INTERVAL 3000
|
||||||
|
|
||||||
#define GP_BABEL_HELLO_TIMEOUT(interval) (16*(interval))
|
#define GP_BABEL_HELLO_TIMEOUT(interval) (16*(interval))
|
||||||
#define GP_BABEL_IHU_TIMEOUT(interval) ((interval)*7/2)
|
#define GP_BABEL_IHU_TIMEOUT(interval) ((interval)*7/2)
|
||||||
|
|
||||||
|
@ -110,11 +115,39 @@ static inline gp_babel_iface_t* gp_babel_get_iface(gmrf_context_t *ctx, gmrf_ifa
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool gp_babel_is_metric_better(gp_babel_metric_seqno_t ms1, gp_babel_metric_seqno_t ms2) {
|
||||||
|
if (ms1.metric == GP_BABEL_INFINITY)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ms2.metric == GP_BABEL_INFINITY)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
int16_t seqno_diff = ms2.seqno - ms1.seqno;
|
||||||
|
|
||||||
|
if (seqno_diff < 0)
|
||||||
|
return true;
|
||||||
|
if (seqno_diff == 0 && ms1.metric < ms2.metric)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool gp_babel_is_feasible(const gp_babel_announce_t *announce, gp_babel_metric_seqno_t ms) {
|
||||||
|
if (ms.metric == GP_BABEL_INFINITY)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return gp_babel_is_metric_better(ms, announce->feasibility_distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void gp_babel_handle_packet(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_iface_t *iface, const gmrf_addr_t *source, const gp_babel_packet_t *packet);
|
void gp_babel_handle_packet(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_iface_t *iface, const gmrf_addr_t *source, const gp_babel_packet_t *packet);
|
||||||
|
|
||||||
void gp_babel_send_ack(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_neigh_t *neigh, uint16_t nonce);
|
void gp_babel_send_ack(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_neigh_t *neigh, uint16_t nonce);
|
||||||
void gp_babel_send_hellos(gmrf_t *gmrf, gmrf_context_t *ctx);
|
void gp_babel_send_hellos(gmrf_t *gmrf, gmrf_context_t *ctx);
|
||||||
|
|
||||||
|
void gp_babel_send_update(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_iface_t *iface, gp_babel_neigh_t *neigh, gp_babel_announce_t *announce, bool with_data);
|
||||||
|
|
||||||
|
|
||||||
gp_babel_announce_t* gp_babel_announce_new(gmrf_t *gmrf, gmrf_context_t *ctx);
|
gp_babel_announce_t* gp_babel_announce_new(gmrf_t *gmrf, gmrf_context_t *ctx);
|
||||||
gp_babel_announce_t* gp_babel_announce_find(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_find(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);
|
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);
|
||||||
|
|
102
src/send.c
102
src/send.c
|
@ -43,6 +43,15 @@ static inline bool send_neigh(gmrf_t *gmrf, const gp_babel_neigh_t *neigh, const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool send_iface(gmrf_t *gmrf, const gp_babel_iface_t *iface, const gp_babel_packet_t *packet) {
|
||||||
|
if (!gmrf_iface_send_bc(gmrf, iface->gmrf_iface, packet, gp_babel_packet_size(packet))) {
|
||||||
|
gmrf_logf(gmrf, LOG_WARNING, "gmrf_iface_send_bc: %m");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void gp_babel_send_ack(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_neigh_t *neigh, uint16_t nonce) {
|
void gp_babel_send_ack(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_neigh_t *neigh, uint16_t nonce) {
|
||||||
gp_babel_packet_buf_t *buf = gp_babel_packet_alloca(GP_BABEL_PACKET_MAX);
|
gp_babel_packet_buf_t *buf = gp_babel_packet_alloca(GP_BABEL_PACKET_MAX);
|
||||||
|
|
||||||
|
@ -90,9 +99,98 @@ void gp_babel_send_hellos(gmrf_t *gmrf, gmrf_context_t *ctx) {
|
||||||
hello->seqno = htons(iface->seqno++);
|
hello->seqno = htons(iface->seqno++);
|
||||||
|
|
||||||
buf->packet.len = len;
|
buf->packet.len = len;
|
||||||
|
|
||||||
add_ihus(gmrf, buf, iface);
|
add_ihus(gmrf, buf, iface);
|
||||||
|
|
||||||
gmrf_iface_send_bc(gmrf, iface->gmrf_iface, &buf->packet, gp_babel_packet_size(&buf->packet));
|
send_iface(gmrf, iface, &buf->packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool add_node_id(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;
|
||||||
|
|
||||||
|
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_data, bool targetted) {
|
||||||
|
if (announce->len && !announce->data) {
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t data_len = (with_data && 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)+data_len);
|
||||||
|
if (!update) {
|
||||||
|
/* reset length to remove possibly added node ID record */
|
||||||
|
buf->packet.len = len;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (data_len)
|
||||||
|
memcpy(update->data, announce->data, data_len);
|
||||||
|
|
||||||
|
if (gp_babel_is_metric_better(announce->metric, announce->feasibility_distance))
|
||||||
|
announce->feasibility_distance = announce->metric;
|
||||||
|
|
||||||
|
if (!targetted)
|
||||||
|
announce->last_metric = announce->metric.metric;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gp_babel_send_update(gmrf_t *gmrf, gmrf_context_t *ctx, gp_babel_iface_t *iface, gp_babel_neigh_t *neigh, gp_babel_announce_t *announce, bool with_data) {
|
||||||
|
gp_babel_packet_buf_t *buf = gp_babel_packet_alloca(GP_BABEL_PACKET_MAX);
|
||||||
|
|
||||||
|
if (announce) {
|
||||||
|
add_update(buf, NULL, announce, with_data, iface || 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_data, iface || neigh)) {
|
||||||
|
if (neigh)
|
||||||
|
send_neigh(gmrf, neigh, &buf->packet);
|
||||||
|
else
|
||||||
|
send_iface(gmrf, iface, &buf->packet);
|
||||||
|
|
||||||
|
node_id = gp_babel_node_id_unspec;
|
||||||
|
buf->packet.len = 0;
|
||||||
|
|
||||||
|
if (!add_update(buf, &node_id, a, with_data, iface || neigh)) {
|
||||||
|
gmrf_logf(gmrf, LOG_ERR, "add_update failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf->packet.len) {
|
||||||
|
if (neigh)
|
||||||
|
send_neigh(gmrf, neigh, &buf->packet);
|
||||||
|
else
|
||||||
|
send_iface(gmrf, iface, &buf->packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,9 @@ typedef struct __attribute__((packed)) gp_gabel_node_id {
|
||||||
uint8_t id[GP_BABEL_NODE_ID_LENGTH];
|
uint8_t id[GP_BABEL_NODE_ID_LENGTH];
|
||||||
} gp_babel_node_id_t;
|
} gp_babel_node_id_t;
|
||||||
|
|
||||||
|
static const gp_babel_node_id_t gp_babel_node_id_unspec = {};
|
||||||
|
|
||||||
|
|
||||||
typedef struct gp_babel_metric_seqno {
|
typedef struct gp_babel_metric_seqno {
|
||||||
uint16_t metric;
|
uint16_t metric;
|
||||||
uint16_t seqno;
|
uint16_t seqno;
|
||||||
|
|
Reference in a new issue