summaryrefslogtreecommitdiffstats
path: root/ffd/ffd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffd/ffd.c')
-rw-r--r--ffd/ffd.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/ffd/ffd.c b/ffd/ffd.c
index f82932a..5e967f3 100644
--- a/ffd/ffd.c
+++ b/ffd/ffd.c
@@ -336,8 +336,15 @@ static void handle_tlv_update(const ffd_tlv_update_t *tlv_update, size_t len, ha
nexthop = new_nexthop(announce, neigh);
}
else {
- if (!feasible && nexthop == announce->selected)
+ if (!feasible && nexthop == announce->selected) {
+ ffd_send_seqno_request_for(neigh, announce);
nexthop = NULL;
+ }
+ }
+
+ if (!feasible && nexthop && nexthop != announce->selected) {
+ if (ms.metric + ffd_neigh_get_cost(neigh) < announce->metric.metric)
+ ffd_send_seqno_request_for(neigh, announce);
}
if ((tlv_update->flags & FFD_UPDATE_WITH_DATA) && !announce->data) {
@@ -369,6 +376,8 @@ static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_
return;
}
+ fprintf(stderr, "debug: received announce request\n");
+
if (ffd_is_node_id_unspec(&tlv_req->node)) {
ffd_send_update(NULL, get_tlv_neigh(arg), NULL, tlv_req->flags & FFD_UPDATE_WITH_DATA);
}
@@ -382,6 +391,48 @@ static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_
}
}
+static void handle_tlv_seqno_req(const ffd_tlv_seqno_req_t *tlv_req, size_t len, handle_tlv_arg_t *arg) {
+ if (len < sizeof(ffd_tlv_seqno_req_t)) {
+ fprintf(stderr, "warn: received short seqno request TLV.\n");
+ return;
+ }
+
+ fprintf(stderr, "debug: received seqno request\n");
+
+ ffd_announce_t *announce = ffd_announce_find(&tlv_req->node, ntohs(tlv_req->type), ntohs(tlv_req->key));
+
+ if (!announce) {
+ fprintf(stderr, "debug: received seqno request for unknown announce\n");
+ return;
+ }
+
+ if (!announce->selected) {
+ fprintf(stderr, "debug: received seqno request for starved announce\n");
+ return;
+ }
+
+ ffd_neigh_t *neigh = get_tlv_neigh(arg);
+
+ if (announce->selected->neigh == neigh)
+ return;
+
+ if ((int16_t)(ntohs(tlv_req->seqno)-announce->selected->metric_seqno.seqno) <= 0) {
+ fprintf(stderr, "debug: received seqno request, seqno already ok\n");
+ ffd_send_update(NULL, neigh, announce, false);
+ return;
+ }
+
+ if (!announce->selected->neigh) {
+ fprintf(stderr, "debug: incrementing seqno\n");
+ announce->selected->metric_seqno.seqno++;
+ ffd_send_update(NULL, neigh, announce, false);
+ return;
+ }
+
+ fprintf(stderr, "debug: received seqno request, forwarding\n");
+ ffd_send_seqno_request(announce->selected->neigh, announce, ntohs(tlv_req->seqno));
+}
+
static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) {
switch (type) {
case TLV_ACK_REQ:
@@ -412,6 +463,10 @@ static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *
handle_tlv_announce_req(data, len, arg);
return;
+ case TLV_SEQNO_REQ:
+ handle_tlv_seqno_req(data, len, arg);
+ return;
+
default:
fprintf(stderr, "debug: received unknown TLV %u on %s.\n", type, ((handle_tlv_arg_t*)arg)->iface->name);
return;
@@ -442,10 +497,8 @@ static void receive_packet(void) {
handle_tlv_arg_t arg = { .iface = get_iface(from.sll_ifindex), .addr = (const eth_addr_t*)&from.sll_addr };
- if (!arg.iface) {
- fprintf(stderr, "debug: received packet on unknown interface.\n");
+ if (!arg.iface)
return;
- }
if (!ffd_tlv_parse(packet, handle_tlv, &arg)) {
fprintf(stderr, "debug: received invalid packet.\n");