Implement handling of seqno requests

This commit is contained in:
Matthias Schiffer 2013-07-29 23:50:39 +02:00
parent 94e334a1fe
commit 45a3ff5a4f
3 changed files with 60 additions and 0 deletions

View file

@ -154,6 +154,12 @@ 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); return gp_babel_node_id_equal(id, &gp_babel_node_id_unspec);
}; };
static inline bool gp_babel_less(uint16_t a, uint16_t b) {
int16_t diff = a - b;
return (diff < 0);
}
static inline bool gp_babel_is_metric_better(gp_babel_metric_seqno_t ms1, gp_babel_metric_seqno_t ms2) { 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) if (ms1.metric == GP_BABEL_INFINITY)
return false; return false;

View file

@ -236,6 +236,7 @@ void gp_babel_send_seqno_request(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, g
req->seqno = htons(seqno); req->seqno = htons(seqno);
req->hop_count = hop_count; req->hop_count = hop_count;
req->reserved = 0;
req->node = announce->node; req->node = announce->node;
req->type = htons(announce->type); req->type = htons(announce->type);
req->key = htons(announce->key); req->key = htons(announce->key);

View file

@ -218,6 +218,55 @@ static void handle_tlv_update(gmrf_context_t *ctx, const gp_babel_tlv_update_t *
gp_babel_announce_update_nexthop(ctx, announce, nexthop, ms, ntohs(tlv_update->interval)); gp_babel_announce_update_nexthop(ctx, announce, nexthop, ms, ntohs(tlv_update->interval));
} }
static void handle_tlv_seqno_req(gmrf_context_t *ctx, const gp_babel_tlv_seqno_req_t *tlv_seqno_req, size_t len, handle_tlv_arg_t *arg) {
if (len < sizeof(gp_babel_tlv_seqno_req_t)) {
gmrf_logf(ctx->gmrf, LOG_WARNING, "received short seqno request TLV.");
return;
}
gp_babel_announce_t *announce = gp_babel_announce_get(ctx, &tlv_seqno_req->node, ntohs(tlv_seqno_req->type), ntohs(tlv_seqno_req->key));
if (!announce || !announce->selected) {
gmrf_logf(ctx->gmrf, LOG_DEBUG, "received seqno request for unknown/unreachable announce.");
return;
}
gmrf_logf(ctx->gmrf, LOG_DEBUG, "seqno request received for %04x%04x, seqno %04x.",
ntohl(*(uint32_t*)tlv_seqno_req->node.id), ntohl(*(uint32_t*)(tlv_seqno_req->node.id+4)),
ntohs(tlv_seqno_req->seqno));
gp_babel_neigh_t *neigh = get_tlv_neigh(arg);
if (!gp_babel_less(announce->metric.seqno, ntohs(tlv_seqno_req->seqno))) {
/* local seqno is high enough */
gmrf_logf(ctx->gmrf, LOG_DEBUG, "sending update.");
gp_babel_send_update(ctx, arg->iface, neigh, announce, false);
return;
}
if (!announce->selected->neigh) {
/* announce is local, increment seqno */
gmrf_logf(ctx->gmrf, LOG_DEBUG, "incrementing seqno.");
announce->selected->metric_seqno.seqno++;
gp_babel_send_update(ctx, arg->iface, neigh, announce, false);
return;
}
if (tlv_seqno_req->hop_count < 2) {
gmrf_logf(ctx->gmrf, LOG_DEBUG, "hopcount too low, discarding.");
return;
}
if (announce->selected->neigh == neigh) {
gmrf_logf(ctx->gmrf, LOG_DEBUG, "not forwarding backwards.");
return;
}
/* forward request */
gmrf_logf(ctx->gmrf, LOG_DEBUG, "forwarding request.");
gp_babel_send_seqno_request(ctx, announce->selected->neigh, announce, ntohs(tlv_seqno_req->seqno), tlv_seqno_req->hop_count-1);
}
static void handle_tlv(gmrf_context_t *ctx, gp_babel_tlv_type_t type, const void *data, size_t len, void *arg) { static void handle_tlv(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;
@ -246,6 +295,10 @@ static void handle_tlv(gmrf_context_t *ctx, gp_babel_tlv_type_t type, const void
handle_tlv_update(ctx, data, len, tlv_arg); handle_tlv_update(ctx, data, len, tlv_arg);
return; return;
case TLV_SEQNO_REQ:
handle_tlv_seqno_req(ctx, data, len, tlv_arg);
return;
default: default:
gmrf_logf(ctx->gmrf, LOG_DEBUG, "received unknown TLV %u on %s.", type, gmrf_iface_get_name(ctx->gmrf, tlv_arg->iface->gmrf_iface)); gmrf_logf(ctx->gmrf, LOG_DEBUG, "received unknown TLV %u on %s.", type, gmrf_iface_get_name(ctx->gmrf, tlv_arg->iface->gmrf_iface));
return; return;