summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/babel.h6
-rw-r--r--src/send.c1
-rw-r--r--src/tlv_types.c53
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;
diff --git a/src/send.c b/src/send.c
index 7512ba7..9f53510 100644
--- a/src/send.c
+++ b/src/send.c
@@ -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;