diff options
-rw-r--r-- | src/babel.h | 6 | ||||
-rw-r--r-- | src/send.c | 1 | ||||
-rw-r--r-- | src/tlv_types.c | 53 |
3 files changed, 60 insertions, 0 deletions
diff --git a/src/babel.h b/src/babel.h index 0d64e9c..41db13d 100644 --- a/src/babel.h +++ b/src/babel.h @@ -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); }; +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) { if (ms1.metric == GP_BABEL_INFINITY) return false; @@ -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->hop_count = hop_count; + req->reserved = 0; req->node = announce->node; req->type = htons(announce->type); req->key = htons(announce->key); diff --git a/src/tlv_types.c b/src/tlv_types.c index 6e94d51..5f077db 100644 --- a/src/tlv_types.c +++ b/src/tlv_types.c @@ -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)); } +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) { 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); return; + case TLV_SEQNO_REQ: + handle_tlv_seqno_req(ctx, data, len, tlv_arg); + return; + 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)); return; |