summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffd/announce.c3
-rw-r--r--ffd/ffd.c61
-rw-r--r--ffd/ffd.h10
-rw-r--r--ffd/send.c18
-rw-r--r--ffd/tlv_types.h6
5 files changed, 89 insertions, 9 deletions
diff --git a/ffd/announce.c b/ffd/announce.c
index 0d7b1bc..26ced28 100644
--- a/ffd/announce.c
+++ b/ffd/announce.c
@@ -116,6 +116,9 @@ void ffd_announce_update(ffd_announce_t *announce) {
announce->selected = select_nexthop(announce);
announce->metric = get_metric(announce);
+ if (!announce->selected)
+ ffd_send_seqno_request_for(NULL, announce);
+
/* triggered updates */
int diff = announce->metric.metric - announce->last_metric;
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");
diff --git a/ffd/ffd.h b/ffd/ffd.h
index 83c4ecb..e7c48d7 100644
--- a/ffd/ffd.h
+++ b/ffd/ffd.h
@@ -39,7 +39,7 @@
#define FFD_HELLO_INTERVAL 400
#define FFD_IHU_INTERVAL (3*FFD_HELLO_INTERVAL)
-#define FFD_UPDATE_INTERVAL 6000
+#define FFD_UPDATE_INTERVAL 3000
#define FFD_HELLO_TIMEOUT(interval) (16*(interval))
#define FFD_IHU_TIMEOUT(interval) ((interval)*7/2)
@@ -195,5 +195,13 @@ void ffd_send_hellos(void);
void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *announce, bool with_data);
void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key);
void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data);
+void ffd_send_seqno_request(ffd_neigh_t *neigh, ffd_announce_t *announce, uint16_t seqno);
+
+static inline void ffd_send_seqno_request_for(ffd_neigh_t *neigh, ffd_announce_t *announce) {
+ if (FFD_IS_INFINITY(announce->feasibility_distance))
+ return;
+
+ ffd_send_seqno_request(neigh, announce, announce->feasibility_distance.seqno+1);
+}
#endif /* _FFD_FFD_H_ */
diff --git a/ffd/send.c b/ffd/send.c
index 9e36456..ebda0de 100644
--- a/ffd/send.c
+++ b/ffd/send.c
@@ -300,3 +300,21 @@ void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_
send_any(iface, neigh, packet);
}
+
+void ffd_send_seqno_request(ffd_neigh_t *neigh, ffd_announce_t *announce, uint16_t seqno) {
+ ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX);
+
+ packet->version_magic = htons(FFD_VERSION_MAGIC);
+ packet->len = 0;
+
+ ffd_tlv_seqno_req_t *req = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_SEQNO_REQ, sizeof(ffd_tlv_seqno_req_t));
+ if (!req)
+ return;
+
+ req->seqno = htons(seqno);
+ req->node = announce->node;
+ req->type = htons(announce->type);
+ req->key = htons(announce->key);
+
+ send_any(NULL, neigh, packet);
+}
diff --git a/ffd/tlv_types.h b/ffd/tlv_types.h
index 07eba53..af3e853 100644
--- a/ffd/tlv_types.h
+++ b/ffd/tlv_types.h
@@ -70,20 +70,18 @@ typedef struct __attribute__((packed)) _ffd_tlv_update_t {
} ffd_tlv_update_t;
typedef struct __attribute__((packed)) _ffd_tlv_announce_req_t {
- ffd_node_id_t node;
uint8_t flags;
uint8_t reserved;
+ ffd_node_id_t node;
uint16_t type;
uint16_t key;
} ffd_tlv_announce_req_t;
typedef struct __attribute__((packed)) _ffd_tlv_seqno_req_t {
+ uint16_t seqno;
ffd_node_id_t node;
- uint8_t flags;
- uint8_t reserved;
uint16_t type;
uint16_t key;
- uint16_t seqno;
} ffd_tlv_seqno_req_t;
#endif /* _FFD_TLV_TYPES_H_ */